bzoj3262: 陌上花开(树套树)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #define maxn 100005 7 #define maxm 200005 8 #define maxk 2000005 9 using namespace std; 10 11 int n,K,temp,tot,root[maxm*4],ans[maxn],Ans[maxn],sum[maxn],fa[maxk],size[maxk],times[maxk],son[maxk][2],val[maxk]; 12 struct seg{ 13 int x,y,z; 14 }a[maxn],b[maxn]; 15 bool comp(seg x,seg y){ 16 if (x.x!=y.x) return x.x<y.x; 17 if (x.y!=y.y) return x.y<y.y; 18 return x.z<y.z; 19 } 20 struct Tsegment{ 21 void prepare(){tot=0,memset(times,0,sizeof(times)),memset(son,0,sizeof(son));} 22 void query(int k,int x,int op){ 23 int y=root[k]; if (y==0) return; bool bo; 24 for (;;){ 25 if (y==0) break; 26 bo=0; 27 if (val[y]==x) ans[op]+=(size[son[y][0]]+times[y]),bo=1; 28 else if (x>val[y]) ans[op]+=(size[son[y][0]]+times[y]),y=son[y][1]; 29 else y=son[y][0]; 30 if (bo==1) break; 31 } 32 } 33 int which(int x){ 34 return son[fa[x]][1]==x; 35 } 36 void update(int x){ 37 size[x]=size[son[x][0]]+size[son[x][1]]+times[x]; 38 } 39 void rotata(int x){ 40 int y=fa[x],d=which(x),dd=which(y); 41 if (fa[y]) son[fa[y]][dd]=x; fa[x]=fa[y]; 42 fa[son[x][d^1]]=y,son[y][d]=son[x][d^1]; 43 fa[y]=x,son[x][d^1]=y,update(y); 44 } 45 void splay(int x,int goal,int op){ 46 while (fa[x]!=goal){ 47 if (fa[fa[x]]==goal) rotata(x); 48 else if (which(x)==which(fa[x])) rotata(fa[x]),rotata(x); 49 else rotata(x),rotata(x); 50 } 51 update(x); if (goal==0) root[op]=x; 52 } 53 void insert(int k,int x,int z){ 54 int y=root[k]; bool bo; 55 if (y==0){ 56 root[k]=++tot,val[tot]=x,size[tot]=times[tot]=z,fa[tot]=son[tot][0]=son[tot][1]=0; 57 return; 58 } 59 for (;;){ 60 bo=0; 61 if (val[y]==x) times[y]+=z,size[y]+=z,bo=1,splay(y,0,k); 62 else if (x<val[y]){ 63 if (!son[y][0]) val[++tot]=x,son[y][0]=tot,fa[tot]=y,size[tot]=times[tot]=z,bo=1,splay(tot,0,k); 64 else y=son[y][0]; 65 }else{ 66 if (!son[y][1]) val[++tot]=x,son[y][1]=tot,fa[tot]=y,size[tot]=times[tot]=z,bo=1,splay(tot,0,k); 67 else y=son[y][1]; 68 } 69 if (bo==1) break; 70 } 71 } 72 }Splay; 73 struct Fsegment{ 74 void prepare(){memset(root,0,sizeof(root));} 75 void query(int k,int l,int r,int x,int y,int z,int op){ 76 if (l>=x&&r<=y){ 77 Splay.query(k,z,op); 78 return; 79 }int mid=(l+r)/2; 80 if (x<=mid) query(k*2,l,mid,x,y,z,op); 81 if (y>mid) query(k*2+1,mid+1,r,x,y,z,op); 82 } 83 void insert(int k,int l,int r,int x,int y,int z){ 84 Splay.insert(k,y,z); 85 if (l==r) return; int mid=(l+r)/2; 86 if (x<=mid) insert(k*2,l,mid,x,y,z); 87 else insert(k*2+1,mid+1,r,x,y,z); 88 } 89 }Tree; 90 struct Ksegment{ 91 void work(){ 92 memset(ans,0,sizeof(ans)); 93 for (int i=1;i<=temp;i++){ 94 Tree.query(1,1,K,1,b[i].y,b[i].z,i); 95 Tree.insert(1,1,K,b[i].y,b[i].z,sum[i]); 96 } 97 memset(Ans,0,sizeof(Ans)); 98 for (int i=1;i<=temp;i++) Ans[ans[i]+sum[i]-1]+=sum[i]; 99 for (int i=0;i<n;i++) printf("%d\n",Ans[i]); 100 } 101 }Task; 102 int main(){ 103 memset(fa,0,sizeof(fa)); 104 memset(son,0,sizeof(son)); 105 memset(val,0,sizeof(val)); 106 a[0].x=a[0].y=a[0].z=0; 107 scanf("%d%d",&n,&K); 108 for (int i=1;i<=n;i++) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z); 109 sort(a+1,a+n+1,comp); 110 memset(sum,0,sizeof(sum)); 111 temp=tot=0; 112 for (int i=1;i<=n;i++){ 113 if (a[i].x==a[i-1].x&&a[i].y==a[i-1].y&&a[i].z==a[i-1].z) sum[temp]++; 114 else sum[++temp]=1,b[temp].x=a[i].x,b[temp].y=a[i].y,b[temp].z=a[i].z; 115 } 116 Tree.prepare(); 117 Task.work(); 118 return 0; 119 }
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3262
题目大意:见题目。
做法:上次我用的是cdq分治+树状数组,这次写的是线段树套splay,比较裸的树套树了,,,一维排序,另外两维在树套树上维护一下即可。
树套树。