bzoj3262: 陌上花开(树套树)

Posted oyzx~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }
View Code

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3262

题目大意:见题目。

做法:上次我用的是cdq分治+树状数组,这次写的是线段树套splay,比较裸的树套树了,,,一维排序,另外两维在树套树上维护一下即可。

树套树。

以上是关于bzoj3262: 陌上花开(树套树)的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ3262陌上花开(CDQ分治)

bzoj3262: 陌上花开

[luogu3810][bzoj3262][陌上花开]

bzoj 3262: 陌上花开

BZOJ3262陌上花开

[BZOJ3262]陌上花开