陌上花開(三維偏序)(cdq分治)
阿新 • • 發佈:2018-12-16
題目連結:https://www.lydsy.com/JudgeOnline/problem.php?id=3262
其實就是三位偏序的模板,cdq分治入門題。
學習cdq分治請看__stdcall大佬的部落格:傳送門
排序來維護第一層,cdq維護一層,樹狀陣列維護一層,然後就沒有啦qwqwq
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #define MAXN 100010 using namespace std; int n,k,cnt; int ans[MAXN],tree[MAXN<<1]; struct Node{int a,b,c,sum,ans;}node[MAXN],now[MAXN]; inline bool cmp1(struct Node x,struct Node y) { if(x.a!=y.a) return x.a<y.a; if(x.b!=y.b) return x.b<y.b; return x.c<y.c; } inline bool cmp2(struct Node x,struct Node y) { if(x.b!=y.b) return x.b<y.b; return x.c<y.c; } inline bool check(struct Node x,struct Node y) { if((x.a==y.a)&&(x.b==y.b)&&(x.c==y.c)) return true; else return false; } inline void add(int x,int val) { for(int i=x;i<=k;i+=(i&-i)) tree[i]+=val; } inline int query(int x) { int cur_ans=0; for(int i=x;i;i-=(i&-i)) cur_ans+=tree[i]; return cur_ans; } inline void cdq(int l,int r) { if(l==r) return; int mid=(l+r)>>1; cdq(l,mid); cdq(mid+1,r); sort(&now[l],&now[mid+1],cmp2); sort(&now[mid+1],&now[r+1],cmp2); int i=l; for(int j=mid+1;j<=r;j++) { while(i<=mid&&now[i].b<=now[j].b) add(now[i].c,now[i].sum),i++; now[j].ans+=query(now[j].c); } for(int j=l;j<i;j++) add(now[j].c,-now[j].sum); } int main() { #ifndef ONLINE_JUDGE freopen("ce.in","r",stdin); #endif scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) scanf("%d%d%d",&node[i].a,&node[i].b,&node[i].c); sort(node+1,node+1+n,cmp1); for(int i=1;i<=n;i++) { if(check(node[i],node[i-1])) now[cnt].sum++; else cnt++,now[cnt]=node[i],now[cnt].sum++; } cdq(1,cnt); for(int i=1;i<=cnt;i++) ans[now[i].ans+now[i].sum-1]+=now[i].sum; for(int i=0;i<n;i++) printf("%d\n",ans[i]); return 0; }