Wc2014 紫荆花之恋

Posted AntiLeaf

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Wc2014 紫荆花之恋相关的知识,希望对你有一定的参考价值。

哈哈哈哈哈哈哈哈哈哈哈哈我终于过了!!!!!!!!!!!!!!!

从昨天上午就开始写了,下午回家之后调了一会儿没什么感觉,就删了重打了一遍,然后调了一晚上+今天半个上午......我*******终于过了......

我是萌萌的传送门

我是另一个萌萌的传送门

一道极其恶心的动态树分治......

首先点分治,限制条件就变成了di+dj<=ri+rj,移项得rj-dj>=di-ri,对重心和子树开平衡树维护di-ri即可。

查询的时候先跳点分治树更新答案,然后逐层把di-ri插入平衡树,上跳的过程中判断是否有子树失衡(某个子树大于子树总大小的alpha倍),有则提出来暴力重构成完全平衡的点分治树。

各种坑爹细节和脑残错误调了一天,不过还是过了,激动......

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<vector>
  5 using namespace std;
  6 const int maxn=100010;
  7 const double alpha=0.7;
  8 struct node{
  9     static int randint(){
 10         static int a=1213,b=97818217,p=998244353,x=751815431;
 11         x=a*x+b;x%=p;
 12         return x<0?(x+=p):x;
 13     }
 14     int data,size,p;
 15     node *ch[2];
 16     node(int d):data(d),size(1),p(randint()){}
 17     inline void refresh(){size=ch[0]->size+ch[1]->size+1;}
 18 }*null=new node(0),*root[maxn],*root1[maxn][50];
 19 void addnode(int,int);
 20 void rebuild(int,int,int,int);
 21 void dfs_getcenter(int,int,int&);
 22 void dfs_getdis(int,int,int,int);
 23 void dfs_destroy(int,int);
 24 void insert(int,node*&);
 25 int order(int,node*);
 26 void destroy(node*&);
 27 void rot(node*&,int);
 28 vector<int>G[maxn],W[maxn];
 29 int size[maxn]={0},siz[maxn][50]={0},son[maxn];
 30 bool vis[maxn];
 31 int depth[maxn],p[maxn],d[maxn][50],id[maxn][50];
 32 int n,m,w[maxn],tmp;
 33 long long ans=0;
 34 int main(){
 35     null->size=0;
 36     null->ch[0]=null->ch[1]=null;
 37     scanf("%*d%d",&n);
 38     fill(vis,vis+n+1,true);
 39     fill(root,root+n+1,null);
 40     for(int i=0;i<=n;i++)fill(root1[i],root1[i]+50,null);
 41     scanf("%*d%*d%d",&w[1]);
 42     insert(-w[1],root[1]);
 43     size[1]=1;
 44     printf("0\\n");
 45     for(int i=2;i<=n;i++){
 46         scanf("%d%d%d",&p[i],&tmp,&w[i]);
 47         p[i]^=(ans%(int)1e9);
 48         G[i].push_back(p[i]);
 49         W[i].push_back(tmp);
 50         G[p[i]].push_back(i);
 51         W[p[i]].push_back(tmp);
 52         addnode(i,tmp);
 53         printf("%lld\\n",ans);
 54     }
 55     return 0;
 56 }
 57 void addnode(int x,int z){//wj-dj>=di-wi
 58     depth[x]=depth[p[x]]+1;
 59     size[x]=1;
 60     insert(-w[x],root[x]);
 61     int rt=0;
 62     for(int u=p[x],k=depth[p[x]];u;u=p[u],k--){
 63         if(u==p[x]){
 64             id[x][k]=x;
 65             d[x][k]=z;
 66         }
 67         else{
 68             id[x][k]=id[p[x]][k];
 69             d[x][k]=d[p[x]][k]+z;
 70         }
 71         ans+=order(w[x]-d[x][k],root[u])-order(w[x]-d[x][k],root1[id[x][k]][k]);
 72         insert(d[x][k]-w[x],root[u]);
 73         insert(d[x][k]-w[x],root1[id[x][k]][k]);
 74         size[u]++;
 75         siz[id[x][k]][k]++;
 76         if(siz[id[x][k]][k]>size[u]*alpha+5)rt=u;
 77     }
 78     id[x][depth[x]]=0;
 79     d[x][depth[x]]=0;
 80     if(rt){
 81         dfs_destroy(rt,depth[rt]);
 82         rebuild(rt,depth[rt],size[rt],p[rt]);
 83     }
 84 }
 85 void rebuild(int x,int k,int s,int pr){
 86     int u=0;
 87     dfs_getcenter(x,s,u);
 88     vis[x=u]=true;
 89     p[x]=pr;
 90     depth[x]=k;
 91     size[x]=s;
 92     d[x][k]=id[x][k]=0;
 93     destroy(root[x]);
 94     insert(-w[x],root[x]);
 95     if(s<=1)return;
 96     for(int i=0;i<(int)G[x].size();i++)if(!vis[G[x][i]]){
 97         p[G[x][i]]=0;
 98         d[G[x][i]][k]=W[x][i];
 99         siz[G[x][i]][k]=p[G[x][i]]=0;
100         destroy(root1[G[x][i]][k]);
101         dfs_getdis(G[x][i],x,G[x][i],k);
102     }
103     for(int i=0;i<(int)G[x].size();i++)if(!vis[G[x][i]])rebuild(G[x][i],k+1,size[G[x][i]],x);
104 }
105 void dfs_getcenter(int x,int s,int &u){
106     size[x]=1;
107     son[x]=0;
108     for(int i=0;i<(int)G[x].size();i++)if(!vis[G[x][i]]&&G[x][i]!=p[x]){
109         p[G[x][i]]=x;
110         dfs_getcenter(G[x][i],s,u);
111         size[x]+=size[G[x][i]];
112         if(size[G[x][i]]>size[son[x]])son[x]=G[x][i];
113     }
114     if(!u||max(s-size[x],size[son[x]])<max(s-size[u],size[son[u]]))u=x;
115 }
116 void dfs_getdis(int x,int u,int rt,int k){
117     insert(d[x][k]-w[x],root[u]);
118     insert(d[x][k]-w[x],root1[rt][k]);
119     id[x][k]=rt;
120     siz[rt][k]++;
121     size[x]=1;
122     for(int i=0;i<(int)G[x].size();i++)if(!vis[G[x][i]]&&G[x][i]!=p[x]){
123         p[G[x][i]]=x;
124         d[G[x][i]][k]=d[x][k]+W[x][i];
125         dfs_getdis(G[x][i],u,rt,k);
126         size[x]+=size[G[x][i]];
127     }
128 }
129 void dfs_destroy(int x,int k){
130     vis[x]=false;
131     for(int i=0;i<(int)G[x].size();i++)if(depth[G[x][i]]>=k&&G[x][i]!=p[x]){
132         p[G[x][i]]=x;
133         dfs_destroy(G[x][i],k);
134     }
135 }
136 void insert(int x,node *&rt){
137     if(rt==null){
138         rt=new node(x);
139         rt->ch[0]=rt->ch[1]=null;
140         return;
141     }
142     int d=x>=rt->data;
143     insert(x,rt->ch[d]);
144     rt->refresh();
145     if(rt->ch[d]->p<rt->p)rot(rt,d^1);
146 }
147 int order(int x,node *rt){
148     int ans=0,d;
149     x++;
150     while(rt!=null){
151         if((d=x>rt->data))ans+=rt->ch[0]->size+1;
152         rt=rt->ch[d];
153     }
154     return ans;
155 }
156 void destroy(node *&x){
157     if(x==null)return;
158     destroy(x->ch[0]);
159     destroy(x->ch[1]);
160     delete x;
161     x=null;
162 }
163 void rot(node *&x,int d){
164     node *y=x->ch[d^1];
165     x->ch[d^1]=y->ch[d];
166     y->ch[d]=x;
167     x->refresh();
168     (x=y)->refresh();
169 }
170 /*
171 Wc2014 紫荆花之恋
172 di+dj<=wi+wj,移项得wj-dj>=di-wi,动态点分治维护即可。
173 每个重心和子树存一棵平衡树维护di-wi,加点的时候跳点分治树更新答案后加入新点,
174 加入之后判断子树是否失衡,找出最高的失衡节点,把整个子树暴力重构成完全平衡的点分治树。
175 */
View Code

 

以上是关于Wc2014 紫荆花之恋的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ3435[Wc2014]紫荆花之恋 替罪点分树+SBT

Wc2014 紫荆花之恋

#55. WC2014紫荆花之恋

[WC2014]紫荆花之恋

luogu P3920 [WC2014]紫荆花之恋

UOJ#55 [WC2014]紫荆花之恋