P4396 [AHOI2013]作业

思路

因为每次a和b不相同
用莫队+分块或者莫队+树状数组即可维护
不过分块单点修改是O(1)的,更优
我用树状数组维护了一下,只能开O2通过

代码

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
struct BIT{
    int tr[10000000],MAXW;
    int lowbit(int x){
        return x&(-x);
    }
    void add(int pos,int c){
        pos++;
        while(pos<=MAXW){
            tr[pos]+=c;
            pos+=lowbit(pos);
        }
    }
    int query(int pos){
        pos++;
        int ans=0;
        while(pos){
            ans+=tr[pos];
            pos-=lowbit(pos);
        }
        return ans;
    }
}times,nums;
int color[10000000],a[100100],n,m,L,R,sz,num,belong[100100],ans1[100100],ans2[100100];
struct Query{
    int l,r,a,b,id;
    bool operator < (const Query &b) const{
        return (belong[l]==belong[b.l])?r<b.r:belong[l]<belong[b.l];
    }
}Q[100100];
void init(void){
    sz=sqrt(n);
    num=n/sz;
    if(n%sz)
        num++;
    for(int i=1;i<=n;i++)
        belong[i]=i/sz+1;
}
void moveL(int opt){
    if(opt==1){
        times.add(a[L],-1);
        if(color[a[L]]==1)
            nums.add(a[L],-1);
        color[a[L]]--;
        L++;
    }
    else{
        L--;
        times.add(a[L],1);
        if(color[a[L]]==0)
            nums.add(a[L],1);
        color[a[L]]++;
    }
}
void moveR(int opt){
    if(opt==1){
        R++;
        times.add(a[R],1);
        if(color[a[R]]==0)
            nums.add(a[R],1);
        color[a[R]]++;    
    }
    else{
        times.add(a[R],-1);
        if(color[a[R]]==1)
            nums.add(a[R],-1);
        color[a[R]]--;
        R--;
    }
}
int main(){
    scanf("%d %d",&n,&m);
    init();
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        times.MAXW=nums.MAXW=max(nums.MAXW,a[i]+10);
    }
    for(int i=1;i<=m;i++)
        scanf("%d %d %d %d",&Q[i].l,&Q[i].r,&Q[i].a,&Q[i].b),Q[i].id=i;
    sort(Q+1,Q+m+1);
    L=R=0;
    for(int i=1;i<=m;i++){
        while(L<Q[i].l)
            moveL(1);
        while(L>Q[i].l)
            moveL(-1);
        while(R<Q[i].r)
            moveR(1);
        while(R>Q[i].r)
            moveR(-1);
        ans1[Q[i].id]=times.query(Q[i].b)-times.query(Q[i].a-1);
        ans2[Q[i].id]=nums.query(Q[i].b)-nums.query(Q[i].a-1);
    }
    for(int i=1;i<=m;i++)
        printf("%d %d\n",ans1[i],ans2[i]);
    return 0;
}

posted @ 2019-05-07 08:53  dreagonm  阅读(141)  评论(0编辑  收藏  举报