<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"><span style="white-space:pre"> </span>题目地址 http://codeforces.com/contest/504/problem/B </span>
这道题目让我更深入的了解了康拓展开。以前只是在做8数码的时候接触了康拓展开了。在比赛的时候想到了康拓展开,但是不知道怎么逆展开,所以没做出来。先介绍一下康拓展开。
康拓展开:
#include<cstdio> #include<algorithm> #include<iostream> #include<cmath> #include<queue> #include<stack> #include<string> #include<cstring> #include<map> #include<vector> #include<set> #include<ctime> #include<stdlib.h> using namespace std; const int mod=99999997; const int mmax=200010; const double eps=1e-8; const double pi=acos(-1.0); const int inf=0x3fffffff; #define debug #define mmax 200010 typedef __int64 LL; int n; int p[mmax],q[mmax],R[mmax],c[mmax]; bool use[mmax]; int low_bit(int x) { return x&(-x); } void updata(int pos) { for(int i=pos;i<=n;i+=low_bit(i)) c[i]++; } int get_sum(int pos) { int ans=0; for(int i=pos;i>0;i-=low_bit(i)) ans+=c[i]; return ans; } int main() { while(cin>>n) { for(int i=1;i<=n;i++) scanf("%d",&p[i]),p[i]++; for(int i=1;i<=n;i++) scanf("%d",&q[i]),q[i]++; memset(c,0,sizeof c); for(int i=1;i<=n;i++) { updata(q[i]); q[i]=q[i]-1-get_sum(q[i]-1); } memset(c,0,sizeof c); for(int i=1;i<=n;i++) { updata(p[i]); p[i]=p[i]-1-get_sum(p[i]-1); } for(int i=1;i<=n;i++) R[i]=q[i]+p[i]; for(int i=n;i>=1;i--) { R[i-1]+=R[i]/(n-i+1); R[i]%=(n-i+1); } memset(c,0,sizeof c); memset(use,0,sizeof use); for(int i=1;i<=n;i++) { int l=R[i]+1,r=n,mid; while(l<r) { mid=(l+r)>>1; if(mid-1-get_sum(mid-1)-R[i]==0&&(!use[mid])) break; if(mid-1-get_sum(mid-1)-R[i]>0) r=mid; else l=mid+1; } mid=(l+r)>>1; R[i]=mid; use[R[i]]=1; updata(R[i]); } for(int i=1;i<=n;i++) { printf("%d%c",R[i]-1,i==n?'\n':' '); } } return 0; }
解法2 康拓展开+平衡树
#include<cstdio> #include<algorithm> #include<iostream> #include<cmath> #include<queue> #include<stack> #include<string> #include<cstring> #include<map> #include<vector> #include<set> #include<ctime> #include<stdlib.h> using namespace std; const int mod=99999997; const int mmax=200010; const double eps=1e-8; const double pi=acos(-1.0); const int inf=0x3fffffff; #define debug #define mmax 200010 typedef __int64 LL; int n; int p[mmax],q[mmax],R[mmax],c[mmax]; bool use[mmax]; int low_bit(int x) { return x&(-x); } void updata(int pos) { for(int i=pos;i<=n;i+=low_bit(i)) c[i]++; } int get_sum(int pos) { int ans=0; for(int i=pos;i>0;i-=low_bit(i)) ans+=c[i]; return ans; } struct Treap { int key,s,r; Treap * ch[2]; Treap(int key0) { key=key0; s=1; r=rand(); ch[0]=ch[1]=0; } void up() { s=1; s+=(ch[0]?ch[0]->s:0); s+=(ch[1]?ch[1]->s:0); } }; typedef Treap * S_Treap ; S_Treap root; void T_clear(S_Treap &p) { if(!p) return ; T_clear(p->ch[0]); T_clear(p->ch[1]); delete p,p=0; } void T_rotate(S_Treap &fa,int d)//d=0左旋 ,d=1右旋 { S_Treap son=fa->ch[d^1]; fa->ch[d^1]=son->ch[d]; son->ch[d]=fa; fa->up(); son->up(); fa=son; } void T_insert(S_Treap &p,int key) { if(!p) { p=new Treap(key); return ; } if(p->key==key) return ; int d=p->key<key; T_insert(p->ch[d],key); if(p->r<p->ch[d]->r) T_rotate(p,d^1); p->up(); } int T_kth(int k,S_Treap root) { if(!root||!(k>=1&&k<=root->s)) return -1; S_Treap p=root; while(1) { int num=p->ch[0]?p->ch[0]->s:0; if(num+1==k) return p->key; else if(num+1>k) p=p->ch[0]; else { p=p->ch[1]; k-=num+1; } } } void f_delete(S_Treap &p,int &key) { if(key == p->key) { if(p->ch[0] && p->ch[1]) { bool d = (p->ch[0]->r > p->ch[1]->r); T_rotate(p, d); f_delete(p->ch[d], key); } else { S_Treap del=p; p = p->ch[p->ch[0] ? 0:1]; delete del,del=0; } } else f_delete(p->ch[p->key < key], key); if(p) p->up(); } int main() { while(cin>>n) { for(int i=1;i<=n;i++) scanf("%d",&p[i]),p[i]++; for(int i=1;i<=n;i++) scanf("%d",&q[i]),q[i]++; memset(c,0,sizeof c); for(int i=1;i<=n;i++) { updata(q[i]); q[i]=q[i]-1-get_sum(q[i]-1); } memset(c,0,sizeof c); for(int i=1;i<=n;i++) { updata(p[i]); p[i]=p[i]-1-get_sum(p[i]-1); } for(int i=1;i<=n;i++) R[i]=q[i]+p[i]; for(int i=n;i>=1;i--) { R[i-1]+=R[i]/(n-i+1); R[i]%=(n-i+1); } T_clear(root); for(int i=1;i<=n;i++) T_insert(root,i); for(int i=1;i<=n;i++) { R[i]=T_kth(R[i]+1,root); f_delete(root,R[i]); } for(int i=1;i<=n;i++) { printf("%d%c",R[i]-1,i==n?'\n':' '); } } return 0; }