BZOJ3435: [Wc2014]紫荆花之恋(替罪羊树,Treap)

Description

强强和萌萌是一对好朋友。有一天他们在外面闲逛,突然看到前方有一棵紫荆树。这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来。仔细看看的话,这个大树实际上是一个带权树。每个时刻它会长出一个新的叶子节点。每个节点上有一个可爱的小精灵,新长出的节点上也会同时出现一个新的小精灵。小精灵是很萌但是也很脆弱的生物,每个小精灵 i 都有一个感受能力值Ri ,小精灵 i, j 成为朋友当且仅当在树上 i 和 j 的距离 dist(i,j) ≤ Ri + Rj,其中 dist(i, j)表示在这个树上从 i 到 j 的唯一路径上所有边的边权和。强强和萌萌很好奇每次新长出一个叶子节点之后,这个树上总共有几对朋友。  
我们假定这个树一开始为空,节点按照加入的顺序从 1开始编号。由于强强非常好奇, 你必须在他每次出现新节点后马上给出总共的朋友对数,不能拖延哦。 

Input

共有 n + 2 行。 
第一行包含一个正整数,表示测试点编号。 
第二行包含一个正整数 n ,表示总共要加入的节点数。 
我们令加入节点前的总共朋友对数是 last_ans,在一开始时它的值为0。 
接下来 n 行中第 i 行有三个数 ai, bi, ri,表示节点  i  的父节点的编号为 ai xor (last_ans mod 10^9)   (其中xor 表示异或,mod  表示取余,数据保证这样操作后得到的结果介于 1到i  –  1之间),与父节点之间的边权为 ci,节点 i 上小精灵的感受能力值为ri。 
注意 a1 = c1 = 0,表示 1 号点是根节点,对于 i > 1,父节点的编号至少为1。

Output

包含 n 行,每行输出1 个整数, 表示加入第 i 个点之后,树上有几对朋友。

Sample Input

0
5
0 0 6
1 2 4
0 9 4
0 5 5
0 2 4

Sample Output

0
1
2
4
7

解题思路:

这道题毒瘤就在于强制在线,假设树是一开始给出的,就是将每个点新的贡献算出来,这个就是淀粉树。
现在考虑如何维护信息,现在分析一下这个式子,求$dis(i,j)\leq r_i+r_j$,在淀粉树上就是$dis(i,t)+dis(t,j)\leq r_i+r_j$
移项得到$r_i-dis(t,i) \geq dis(t,j)-r_j$,在淀粉中心维护一下容斥一下和那个震波就一样了。
只不过这里的计数是考虑比$r_i-dis(t,i)$小的$dis(t,j)-r_j$个数,维护$dis(t,j)$,查询$r_i-dis(t,i)$排名就好了。
这里的淀粉树不可以直接建出来。但是树高是log级别的,像替罪羊一样重构就好了。
卡常略微恶心,BZOJ上卡过了,luogu上开了O3调了半天$\alpha$最后0.77才过。
代码:
  1 #include<ctime>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cstdlib>
  5 #include<algorithm>
  6 #define lll tr[spc].ls
  7 #define rrr tr[spc].rs
  8 typedef long long lnt;
  9 const double alpha=0.77;
 10 struct pnt{
 11     int hd;
 12     int F;
 13     int T;
 14     int dp;
 15     int val;
 16     int wgt;
 17     int wgt_;
 18     int fa[20];
 19     int root;
 20     int root_;
 21     lnt dis;
 22     bool vis;
 23 }p[2000000];
 24 struct ent{
 25     int twd;
 26     int lst;
 27     int vls;
 28 }e[2000000];
 29 struct trnt{
 30     int ls;
 31     int rs;
 32     int val;
 33     int wgt;
 34     int rnd;
 35 }tr[10000000],BLANK_TRNT;
 36 int siz;
 37 int top;
 38 int cnt;
 39 int tot;
 40 int tms;
 41 int root;
 42 int maxval;
 43 int n,test_no;
 44 lnt lastans;
 45 int bin[10000000];
 46 void del(int &spc)
 47 {
 48     if(!spc)return ;
 49     bin[++top]=spc;
 50     spc=0;
 51     return ;
 52 }
 53 int newp(void)
 54 {
 55     if(top)
 56     {
 57         int spc=bin[top--];
 58         if(lll)bin[++top]=lll;
 59         if(rrr)bin[++top]=rrr;
 60         return spc;
 61     }
 62     return ++siz;
 63 }
 64 int apply(int v)
 65 {
 66     int spc=newp();
 67     tr[spc]=BLANK_TRNT;
 68     tr[spc].val=v;
 69     tr[spc].rnd=rand();
 70     tr[spc].wgt=1;
 71     return spc;
 72 }
 73 void pushup(int spc)
 74 {
 75     tr[spc].wgt=tr[lll].wgt+tr[rrr].wgt+1;
 76     return ;
 77 }
 78 void lturn(int &spc)
 79 {
 80     int tmp=lll;
 81     lll=tr[tmp].rs;
 82     tr[tmp].rs=spc;
 83     pushup(spc);
 84     pushup(tmp);
 85     spc=tmp;
 86     return ;
 87 }
 88 void rturn(int &spc)
 89 {
 90     int tmp=rrr;
 91     rrr=tr[tmp].ls;
 92     tr[tmp].ls=spc;
 93     pushup(spc);
 94     pushup(tmp);
 95     spc=tmp;
 96 }
 97 void insert(int &spc,int v)
 98 {
 99     if(!spc)
100     {
101         spc=apply(v);
102         return ;
103     }
104     if(tr[spc].val<v)
105     {
106         insert(rrr,v);
107         if(tr[rrr].rnd<tr[spc].rnd)rturn(spc);
108     }else{
109         insert(lll,v);
110         if(tr[lll].rnd<tr[spc].rnd)lturn(spc);
111     }
112     pushup(spc);
113     return ;
114 }
115 int rank(int spc,int v)
116 {
117     int ans=0;
118     while(spc)
119     {
120         if(tr[spc].val<v)
121         {
122             ans+=tr[lll].wgt+1;
123             spc=rrr;
124         }else spc=lll;
125     }
126     return ans;
127 }
128 //------------^Treap
129 void ade(int f,int t,int v)
130 {
131     if(!f||!t)return ;
132     cnt++;
133     e[cnt].twd=t;
134     e[cnt].vls=v;
135     e[cnt].lst=p[f].hd;
136     p[f].hd=cnt;
137     return ;
138 }
139 void decode(int &tmp_a)
140 {
141     tmp_a^=(lastans%1000000000);
142     return ;
143 }
144 int lca(int x,int y)
145 {
146     if(p[x].dp<p[y].dp)std::swap(x,y);
147     for(int i=17;i>=0;i--)
148         if(p[p[x].fa[i]].dp>=p[y].dp)
149             x=p[x].fa[i];
150     if(x==y)return x;
151     for(int i=17;i>=0;i--)
152     {
153         if(p[x].fa[i]!=p[y].fa[i])
154         {
155             x=p[x].fa[i];
156             y=p[y].fa[i];
157         }
158     }
159     return p[x].fa[0];
160 }
161 lnt dis(int x,int y)
162 {
163     return p[x].dis+p[y].dis-p[lca(x,y)].dis*2;
164 }
165 void kill(int x,int f,int t)
166 {
167     tot++;
168     p[x].wgt_=0;
169     p[x].T=tms;
170     p[x].vis=false;
171     del(p[x].root);
172     del(p[x].root_);
173     for(int i=p[x].hd;i;i=e[i].lst)
174     {
175         int to=e[i].twd;
176         if(to==f||p[to].wgt_>t)continue;
177         kill(to,x,t);
178     }
179     return ;
180 }
181 void grc_dfs(int x,int f)
182 {
183     p[x].wgt=1;
184     int maxs=0;
185     for(int i=p[x].hd;i;i=e[i].lst)
186     {
187         int to=e[i].twd;
188         if(to==f||p[to].vis)continue;
189         grc_dfs(to,x);
190         p[x].wgt+=p[to].wgt;
191         maxs=std::max(maxs,p[to].wgt);
192     }
193     maxs=std::max(maxs,tot-p[x].wgt);
194     if(maxs<maxval)
195     {
196         root=x;
197         maxval=maxs;
198     }
199     return ;
200 }
201 void bin_dfs(int x,int F)
202 {
203     p[x].F=F;
204     p[x].vis=true;
205     int tmpv=tot;
206     for(int i=p[x].hd;i;i=e[i].lst)
207     {
208         int to=e[i].twd;
209         if(p[to].vis)continue;
210         if(p[x].wgt>p[to].wgt)tot=p[to].wgt;
211         else                  tot=tmpv-p[x].wgt;
212         root=0;
213         maxval=0x3f3f3f3f;
214         grc_dfs(to,to);
215         bin_dfs(root,x);
216     }
217     return ;
218 }
219 void relive(int x,int f,int F)
220 {
221     for(int i=x;i!=F;i=p[i].F)
222     {
223         p[i].wgt_++;
224         insert(p[i].root,dis(x,i)-p[x].val);
225         if(!p[i].F)break;
226         insert(p[i].root_,dis(p[i].F,x)-p[x].val);
227     }
228     for(int i=p[x].hd;i;i=e[i].lst)
229     {
230         int to=e[i].twd;
231         if(p[to].T!=tms||to==f)continue;
232         relive(to,x,F);
233     }
234     return ;
235 }
236 void rebuild(int x)
237 {
238     tms++;
239     int F=p[x].F;
240     tot=0;
241     root=0;
242     maxval=0x3f3f3f3f;
243     kill(x,x,p[x].wgt_);
244     grc_dfs(x,x);
245     bin_dfs(root,F);
246     relive(x,x,F);
247     return ;
248 }
249 void T_insert(int x)
250 {
251     int plc=0;
252     p[x].wgt_=1;
253     insert(p[x].root,-p[x].val);
254     for(int i=x;p[i].F;i=p[i].F)
255     {
256         insert(p[p[i].F].root,dis(p[i].F,x)-p[x].val);
257         insert(p[i].root_,dis(p[i].F,x)-p[x].val);
258         p[p[i].F].wgt_++;
259         if(1.00*p[i].wgt_>alpha*p[p[i].F].wgt_)plc=p[i].F;
260     }
261     if(plc)rebuild(plc);
262     return ;
263 }
264 lnt T_query(int x)
265 {
266     lnt ans=rank(p[x].root,p[x].val+1)-1;
267     for(int i=x;p[i].F;i=p[i].F)
268     {
269         ans+=rank(p[p[i].F].root,p[x].val-dis(p[i].F,x)+1);
270         ans-=rank(p[i].root_,p[x].val-dis(p[i].F,x)+1);
271     }
272     return ans;
273 }
274 int main()
275 {
276     scanf("%d",&test_no);
277     scanf("%d",&n);
278     for(int i=1;i<=n;i++)
279     {
280         p[i].vis=true;
281         int a,b,c;
282         scanf("%d%d%d",&a,&b,&c);
283         decode(a);
284         p[i].F=a;
285         p[i].val=c;
286         p[i].dp=p[a].dp+1;
287         p[i].dis=p[a].dis+b;
288         if(i!=1)p[i].fa[0]=a;
289         else    p[i].fa[0]=1;
290         for(int j=1;j<=17;j++)p[i].fa[j]=p[p[i].fa[j-1]].fa[j-1];
291         ade(i,a,b);ade(a,i,b);
292         T_insert(i);
293         lastans+=T_query(i);
294         printf("%lld\n",lastans);
295     }
296     return 0;
297 }

转载于:https://www.cnblogs.com/blog-Dr-J/p/10447487.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值