P3810 【模板】三維偏序(陌上花開)(cdq分治)
阿新 • • 發佈:2018-12-15
思路
看到這種偏序類的題目,而且不要求強制線上,可以立刻想到cdq分治
注意這題有一個問題,就是詢問的是小於等於而不是小於,如果相等的話兩個元素會相互貢獻,而cdq的特點是右區間不能對左邊有影響,所以要先去重,再然後就是板子
程式碼
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; int n,maxn; namespace BIT{ int bit[200100]; int lowbit(int x){ return x&(-x); } void add(int pos,int val){ while(pos<=maxn){ bit[pos]+=val; pos+=lowbit(pos); } } int query(int pos){ int ans=0; while(pos){ ans+=bit[pos]; pos-=lowbit(pos); } return ans; } void clear(int pos){ while(pos<=maxn){ if(bit[pos]) bit[pos]=0; else break; pos+=lowbit(pos); } } } struct Num{ int a,b,c,val; bool operator == (const Num &bx) const{ if(a==bx.a&&b==bx.b&&c==bx.c) return true; return false; } bool operator < (const Num &bx) const{ if(a<bx.a) return true; else if(a==bx.a&&b<bx.b) return true; else if(a==bx.a&&b==bx.b&&c<bx.c) return true; else return false; } }a[100100],num[100100]; int ans[100100],d[100100]; int cntnum=0,qid,aid; struct Query{ int posx,valy,val,aid; }query[100100<<1]; Query tmp[100100<<1]; void cdq(int L,int R){ // printf("%d %d\n",L,R); if(R<=L+1) return; int mid=(L+R)>>1; cdq(L,mid); cdq(mid,R); int l=L,r=mid,tot=0; while(l<mid&&r<R){ if(query[l].posx<=query[r].posx){ BIT::add(query[l].valy,query[l].val); tmp[++tot]=query[l++]; } else{ ans[query[r].aid]+=BIT::query(query[r].valy); tmp[++tot]=query[r++]; } } while(l<mid) tmp[++tot]=query[l++]; while(r<R){ ans[query[r].aid]+=BIT::query(query[r].valy); tmp[++tot]=query[r++]; } for(int i=1;i<=tot;i++){ BIT::clear(tmp[i].valy); query[i+L-1]=tmp[i]; } } int main(){ scanf("%d %d",&n,&maxn); for(int i=1;i<=n;i++) scanf("%d %d %d",&a[i].a,&a[i].b,&a[i].c),a[i].val=1; sort(a+1,a+n+1); // printf("ok\n"); // for(int i=1;i<=n;i++) // printf("%d %d %d\n",a[i].a,a[i].b,a[i].c); num[++cntnum]=a[1]; for(int i=1;i<=n-1;i++){ if(a[i]==a[i+1]) num[cntnum].val++; else num[++cntnum]=a[i+1]; } for(int i=1;i<=cntnum;i++){ query[++qid].posx=num[i].b; query[qid].aid=++aid; query[qid].valy=num[i].c; query[qid].val=num[i].val; } // printf("ok\n"); cdq(1,qid+1); for(int i=1;i<=qid;i++){ d[ans[query[i].aid]+query[i].val-1]+=query[i].val; } for(int i=0;i<=n-1;i++) printf("%d\n",d[i]); return 0; }