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 */

时间: 2024-10-07 16:49:06

Wc2014 紫荆花之恋的相关文章

bzoj 3435: [Wc2014]紫荆花之恋 替罪羊树维护点分治 &amp;&amp; AC400

3435: [Wc2014]紫荆花之恋 Time Limit: 240 Sec  Memory Limit: 512 MBSubmit: 159  Solved: 40[Submit][Status][Discuss] Description 强 强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来. 仔细看看的话,这个大树实际上是一个带权树.每个时刻它会长出一个新的叶子节点.每个节点上有一个可爱的小精灵,

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

[BZOJ3435][Wc2014]紫荆花之恋 Description 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来.仔细看看的话,这个大树实际上是一个带权树.每个时刻它会长出一个新的叶子节点.每个节点上有一个可爱的小精灵,新长出的节点上也会同时出现一个新的小精灵.小精灵是很萌但是也很脆弱的生物,每个小精灵 i 都有一个感受能力值Ri ,小精灵 i, j 成为朋友当且仅当在树上 i 和 j 的距离

BZOJ 3435: [Wc2014]紫荆花之恋

二次联通门 : BZOJ 3435: [Wc2014]紫荆花之恋 二次联通门 : luogu P3920 [WC2014]紫荆花之恋 /* luogu P3920 [WC2014]紫荆花之恋 怀疑人生 */ #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <ctime> #include <algorithm> #de

【bzoj3435】[Wc2014]紫荆花之恋 替罪点分树套SBT

题目描述 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来.仔细看看的话,这个大树实际上是一个带权树.每个时刻它会长出一个新的叶子节点.每个节点上有一个可爱的小精灵,新长出的节点上也会同时出现一个新的小精灵.小精灵是很萌但是也很脆弱的生物,每个小精灵 i 都有一个感受能力值Ri ,小精灵 i, j 成为朋友当且仅当在树上 i 和 j 的距离 dist(i,j) ≤ Ri + R! ,其中 dist(i

UOJ#55 [WC2014]紫荆花之恋

题目描述 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来. 仔细看看的话,这个大树实际上是一个带权树.每个时刻它会长出一个新的叶子节点,每个节点上有一个可爱的小精灵,新长出的节点上也会同时出现一个新的小精灵.小精灵是很萌但是也很脆弱的生物,每个小精灵 \(i\) 都有一个感受能力值 \(r_i\),小精灵 \(i, j\) 成为朋友当且仅当在树上 \(i\) 和 \(j\) 的距离 \(\text{

BZOJ 3435 Wc2014 紫荆花之恋 动态树分治+替罪羊树+Treap

题目大意:给定一棵树,每次添加一个节点并询问当前有多少点对满足dis(i,j)<=ri+rj 强制在线 吾辈有生之年终于把这道题切了...QAQ 什么?你想做这题? 1095切了么?没?去把1095切掉再说! 3065切了么?没?去把3065切掉再说! 什么?都切了?那还不会做这题?? -- 算了还是说说做法吧... 我们抛开那些乱七八糟的,考虑朴素做法 首先式子的形式是dis(i,j)<=ri+rj,令p=lca(i,j),把式子变形可以得到dis(j,p)-rj<=ri-dis(i,

P3920 [WC2014]紫荆花之恋 [点分树,替罪羊树]

点分树搞出来,然后搞个快点的平衡树. 点分树膨胀的时候就搞重构,没了...说的这么轻巧倒是写了3h 23333 // powered by c++11 // by Isaunoya #include <bits/stdc++.h> #define rep(i, x, y) for (register int i = (x); i <= (y); ++i) #define Rep(i, x, y) for (register int i = (x); i >= (y); --i) #

#55. 【WC2014】紫荆花之恋

强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来. 仔细看看的话,这个大树实际上是一个带权树.每个时刻它会长出一个新的叶子节点,每个节点上有一个可爱的小精灵,新长出的节点上也会同时出现一个新的小精灵.小精灵是很萌但是也很脆弱的生物,每个小精灵 ii 都有一个感受能力值 riri,小精灵 i,ji,j 成为朋友当且仅当在树上 ii 和 jj 的距离 dist(i,j)≤ri+rjdist(i,j)≤ri

数据结构(平衡树,树分治,暴力重构):WC 2014 紫荆花之恋

[题目描述] 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来. 仔细看看的话,这棵大树实际上是一个带权树.每个时刻他会长出一个新的叶子节点.每个节点上有一个可爱的小精灵,新长出的节点上也会同时出现一个新的小精 灵.小精灵是很萌但是也很脆弱的生物,每个小精灵i都有一个感受能力ri,小精灵i,j成为朋友当且仅当在树上i和j的距离 dist(i,j)<=ri+rj,其中dist(i,j)表示在这棵树上i和