suoj20 垃圾显示屏(cdq分治+树状数组)

来源:互联网 发布:喜马拉雅 知乎 编辑:程序博客网 时间:2024/06/05 19:17

二维平面,两种操作
1.给(x,y) +1
2.查询矩形(1,1,x,y)的权值和。
二维树状数组开不下,cdq分治,去掉一维,然后用树状数组维护。O(nlog2n)

#include <cstdio>#include <cstring>using namespace std;#define ll long long#define inf 0x3f3f3f3f#define N 200010#define mod 1000000007inline int read(){    int x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();    return x*f;}int n,c[10010],num=0,ans[N];struct oper{    int op,x,y,id;    friend bool operator<(oper a,oper b){        return a.x==b.x?a.op<b.op:a.x<b.x;//x从小到大做,x相等时修改在询问前面     }}q[N],tmp[N];inline void add(int x){    for(;x<=10000;x+=x&-x) c[x]++;}inline int ask(int x){    int res=0;for(;x;x-=x&-x) res+=c[x];return res;}inline void cdq(int l,int r){    if(l==r) return;    int mid=l+r>>1,owo=0;cdq(l,mid);cdq(mid+1,r);    int p1=l,p2=mid+1;memset(c,0,sizeof(c));    while(p1<=mid&&p2<=r){        if(q[p1]<q[p2]){            if(q[p1].op==0) add(q[p1].y);            tmp[++owo]=q[p1++];        }else{            if(q[p2].op==1) ans[q[p2].id]+=ask(q[p2].y);            tmp[++owo]=q[p2++];        }    }while(p1<=mid) tmp[++owo]=q[p1++];    while(p2<=r){        if(q[p2].op==1) ans[q[p2].id]+=ask(q[p2].y);        tmp[++owo]=q[p2++];    }for(int i=l;i<=r;++i) q[i]=tmp[i-l+1];}int main(){//  freopen("a.in","r",stdin);    n=read();for(int i=1;i<=n;++i){        char op[5];scanf("%s",op+1);int x=read(),y=read();        if(op[1]=='Q'){q[i].op=1;q[i].x=x;q[i].y=y;q[i].id=++num;}        else q[i].op=0,q[i].x=x,q[i].y=y;    }cdq(1,n);    for(int i=1;i<=num;++i) printf("%d\n",ans[i]);    return 0;}
阅读全文
0 0