1. 程式人生 > 其它 >陌上花開,可緩緩歸矣

陌上花開,可緩緩歸矣

陌上花開,可緩緩歸矣(三維偏序)

其實是想複習樹狀陣列和歸併排序

cdq分治noip考完再說

一、歸併排序(merge sort)

採用分治策略,分而治之,直接上原理圖

看上去像個完全二叉樹,所以遞迴解決,復l雜度nlog2n

遞迴分到最後,只有一個元素顯然是有序的,這時候再進行二路歸併,具體如下圖

上程式碼(逆序對

#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+10;
int a[maxn],f[maxn];
long long p;
void s(int l,int r)
{
int
k,i,m,j; if(l==r) return; m=(l+r)/2; s(l,m); s(m+1,r);//先分 j=m+1,i=l,k=l; while(i<=m&&j<=r) { if(a[i]>a[j]) { p+=m-i+1;//統計逆序對 f[k]=a[j];//存入新陣列 j++,k++; } else { f[k]=a[i]; i++,k++; } } while(i<=m) { f[k]=a[i]; i++,k++; } while(j<=r) { f[k]=a[j]; j++,k++; }//將剩餘元素壓入 for(int q=l;q<=r;q++) a[q]=f[q];//
修改原陣列,保證後續歸併的正確性 } int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } s(1,n); printf("%lld",p); return 0; }
View Code

然後你就學會啦

二、樹狀陣列

這個要不專門講吧

我們下一篇部落格見AWA

三、三維偏序

cdq分治

離散化+歸併排序降維打擊+樹狀陣列計數

具體的退役了再完善吧

上程式碼

#include<bits/stdc++.h>
using  namespace std;
const int N=2e5+100; struct node { int a,b,c,f,w; }e[N],g[N]; int d[N],n,k,cnt,ans[N]; int lowbit(int x) { return x&(-x); } void add(int x,int y) { while(x<=k) { d[x]+=y; x+=lowbit(x); } } int find(int x) { int ans=0; while(x!=0) { ans+=d[x]; x-=lowbit(x); } return ans; } bool cmp(node x,node y) { if(x.a==y.a) { if(x.b==y.b) return x.c<y.c; else return x.b<y.b; } else return x.a<y.a; } void cdq(int l,int r) { int mid=(l+r)/2; if(l==r) return; cdq(l,mid); cdq(mid+1,r); int h=l,t=mid+1,tot=l; while(h<=mid&&t<=r) { if(g[h].b<=g[t].b) { add(g[h].c,g[h].w); e[tot++]=g[h++]; } else { g[t].f+=find(g[t].c); e[tot++]=g[t++]; } } while(h<=mid) { add(g[h].c,g[h].w); e[tot++]=g[h++]; } while(t<=r) { g[t].f+=find(g[t].c); e[tot++]=g[t++]; } for(int i=l;i<=mid;i++) add(g[i].c,-g[i].w); for(int i=l;i<=r;i++) g[i]=e[i]; } int main() { cin>>n>>k; for(int i=1;i<=n;i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); e[i].a=x; e[i].b=y; e[i].c=z; } sort(e+1,e+1+n,cmp); for(int i=1;i<=n;i++) { if(e[i].a!=g[cnt].a||e[i].b!=g[cnt].b||e[i].c!=g[cnt].c) { g[++cnt]=e[i]; g[cnt].w=1; } else g[cnt].w++; } cdq(1,cnt); for(int i=1;i<=cnt;i++) { if(g[i].w==1) ans[g[i].f]++; if(g[i].w>1) ans[g[i].f+g[i].w-1]+=g[i].w; } for(int i=0;i<n;i++) cout<<ans[i]<<endl; return 0; }
View Code