bzoj 3236: [Ahoi2013]作业(缺线段树)

Posted 一蓑烟雨任生平

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 3236: [Ahoi2013]作业(缺线段树)相关的知识,希望对你有一定的参考价值。

3236: [Ahoi2013]作业

Time Limit: 100 Sec  Memory Limit: 512 MB
Submit: 1744  Solved: 702
[Submit][Status][Discuss]

Description

技术分享

 

Input

技术分享

Output

技术分享

Sample Input

3 4
1 2 2
1 2 1 3
1 2 1 1
1 3 1 3
2 3 2 3

Sample Output

2 2
1 1
3 2
2 1

HINT

 

N=100000,M=1000000

 

Source

By wangyisong1996加强数据

思路:莫队套权值树状数组。

错因:数组开小了。

莫队套树状数组:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 1000001
using namespace std;
int n,m,S,ans;
int num[MAXN],sum[MAXN],c[2][MAXN];
struct nond{
    int l,r,a,b;
    int id,pos,ans,sum;
}edge[MAXN];
int cmp(nond a,nond b){
    if(a.pos==b.pos)    return a.r<b.r;
    else return a.pos<b.pos;
}
int cmp1(nond a,nond b){
    return a.id<b.id;
}
int lowbit(int x){
    return x&(-x);
}
void change(int k,int w,int h){
    while(k<=n){
        c[h][k]+=w;
        k+=lowbit(k);        
    }
}
int query(int k,int h){
    int tot=0;
    while(k){
        tot+=c[h][k];
        k-=lowbit(k);
    }
    return tot;
}
void up(int x,int k){
    sum[num[x]]+=k;
    change(num[x],k,1);
    if(k==1&&sum[num[x]]==1)    change(num[x],k,0);
    else if(k==-1&&sum[num[x]]==0)    change(num[x],k,0);
}
void mode(){
    int l=1,r=0;
    for(int i=1;i<=m;i++){
        while(l<edge[i].l) up(l++,-1);
        while(l>edge[i].l) up(--l,1);
        while(r<edge[i].r) up(++r,1);
        while(r>edge[i].r) up(r--,-1);
        edge[i].sum=query(edge[i].b,0)-query(edge[i].a-1,0);
        edge[i].ans=query(edge[i].b,1)-query(edge[i].a-1,1);
    }
}
int main(){
    freopen("ahoi2013_homework.in","r",stdin);
    freopen("ahoi2013_homework.out","w",stdout);
    scanf("%d%d",&n,&m);
    S=sqrt(n);
    for(int i=1;i<=n;i++)
        scanf("%d",&num[i]);
    for(int i=1;i<=m;i++){
        scanf("%d%d%d%d",&edge[i].l,&edge[i].r,&edge[i].a,&edge[i].b);
        edge[i].id=i;
        edge[i].pos=(edge[i].l-1)/S+1;
    }
    sort(edge+1,edge+1+m,cmp);
    mode();
    sort(edge+1,edge+1+m,cmp1);
    for(int i=1;i<=m;i++)
        cout<<edge[i].ans<<" "<<edge[i].sum<<endl;
}

莫队套线段树:

 

以上是关于bzoj 3236: [Ahoi2013]作业(缺线段树)的主要内容,如果未能解决你的问题,请参考以下文章

AC日记——[Ahoi2013]作业 bzoj 3236

BZOJ3236:[AHOI2013]作业——题解

BZOJ3236: [Ahoi2013]作业

BZOJ3236: [Ahoi2013]作业 树状数组维护 莫队

[BZOJ3238][Ahoi2013]差异

bzoj3238 [Ahoi2013]差异