BZOJ 3236 莫队+树状数组

思路:
莫队+树状数组

(据说此题卡常数)

yzy写了一天(偷笑)

复杂度有点儿爆炸 O(msqrt(n)logn)

//By SiriusRen
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 1005000
int n,m,a[N],pos[N],w[N],W[N],tmp,ww[N];
struct Node{int l,r,a,b,ansx,ansy,id;}node[N];
bool cmp(Node a,Node b){if(pos[a.l]==pos[b.l])return a.r<b.r;return a.l<b.l;}
bool cmp2(Node a,Node b){return a.id<b.id;}
int lowbit(int x){return x&(-x);}
int sum(int x){int ans=0;for(int i=x;i;i-=lowbit(i))ans+=w[i];return ans;}
void add(int x,int z){for(int i=x;i<=n;i+=lowbit(i))w[i]+=z;}
int sum2(int x){int ans=0;for(int i=x;i;i-=lowbit(i))ans+=ww[i];return ans;}
void add2(int x,int z){for(int i=x;i<=n;i+=lowbit(i))ww[i]+=z;}
void update(int x,int wei){
    if(!W[x])add2(x,1);
    add(x,wei);
    W[x]+=wei;
    if(!W[x])add2(x,-1);
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int i=1;i<=m;node[i].id=i,i++)scanf("%d%d%d%d",&node[i].l,&node[i].r,&node[i].a,&node[i].b);
    int block=sqrt(n);
    for(int i=1;i<=n;i++)pos[i]=(i-1)/block+1;
    sort(node+1,node+1+m,cmp);
    for(int i=1,l=1,r=0;i<=m;i++){
        for(;r<node[i].r;r++)update(a[r+1],1);
        for(;r>node[i].r;r--)update(a[r],-1);
        for(;l<node[i].l;l++)update(a[l],-1);
        for(;l>node[i].l;l--)update(a[l-1],1);
        node[i].ansx=sum(node[i].b)-sum(node[i].a-1);
        node[i].ansy=sum2(node[i].b)-sum2(node[i].a-1);
    }
    sort(node+1,node+1+m,cmp2);
    for(int i=1;i<=m;i++)
        printf("%d %d\n",node[i].ansx,node[i].ansy);
}

这里写图片描述

posted @ 2016-12-20 21:53  SiriusRen  阅读(138)  评论(0编辑  收藏  举报