bzoj4012: [HNOI2015]开店

Posted OldJang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj4012: [HNOI2015]开店相关的知识,希望对你有一定的参考价值。

 

人生哲学。最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱。这样的
想法当然非常好啦,但是她们也发现她们面临着一个问题,那就是店开在哪里,面
向什么样的人群。很神奇的是,幻想乡的地图是一个树形结构,幻想乡一共有 n
个地方,编号为 1 到 n,被 n-1 条带权的边连接起来。每个地方都住着一个妖怪,
其中第 i 个地方的妖怪年龄是 x_i。妖怪都是些比较喜欢安静的家伙,所以它们并
不希望和很多妖怪相邻。所以这个树所有顶点的度数都小于或等于 3。妖怪和人一
样,兴趣点随着年龄的变化自然就会变化,比如我们的 18 岁少女幽香和八云紫就
比较喜欢可爱的东西。幽香通过研究发现,基本上妖怪的兴趣只跟年龄有关,所以
幽香打算选择一个地方 u(u为编号),然后在 u开一家面向年龄在 L到R 之间(即
年龄大于等于 L、小于等于 R)的妖怪的店。也有可能 u这个地方离这些妖怪比较
远,于是幽香就想要知道所有年龄在 L 到 R 之间的妖怪,到点 u 的距离的和是多
少(妖怪到 u 的距离是该妖怪所在地方到 u 的路径上的边的权之和) ,幽香把这个
称为这个开店方案的方便值。幽香她们还没有决定要把店开在哪里,八云紫倒是准
备了很多方案,于是幽香想要知道,对于每个方案,方便值是多少呢。
 

Input

 第一行三个用空格分开的数 n、Q和A,表示树的大小、开店的方案个数和妖

怪的年龄上限。 
第二行n个用空格分开的数 x_1、x_2、…、x_n,x_i 表示第i 个地点妖怪的年
龄,满足0<=x_i<A。(年龄是可以为 0的,例如刚出生的妖怪的年龄为 0。) 
接下来 n-1 行,每行三个用空格分开的数 a、b、c,表示树上的顶点 a 和 b 之
间有一条权为c(1 <= c <= 1000)的边,a和b 是顶点编号。 
接下来Q行,每行三个用空格分开的数 u、 a、 b。对于这 Q行的每一行,用 a、
b、A计算出 L和R,表示询问“在地方 u开店,面向妖怪的年龄区间为[L,R]的方
案的方便值是多少”。对于其中第 1 行,L 和 R 的计算方法为:L=min(a%A,b%A), 
R=max(a%A,b%A)。对于第 2到第 Q行,假设前一行得到的方便值为 ans,那么当
前行的 L 和 R 计算方法为: L=min((a+ans)%A,(b+ans)%A), 
R=max((a+ans)%A,(b+ans)%A)。 
 

Output

对于每个方案,输出一行表示方便值。 

 

Sample Input

10 10 10
0 0 7 2 1 4 7 7 7 9
1 2 270
2 3 217
1 4 326
2 5 361
4 6 116
3 7 38
1 8 800
6 9 210
7 10 278
8 9 8
2 8 0
9 3 1
8 0 8
4 2 7
9 7 3
4 7 0
2 2 7
3 2 1
2 3 4

Sample Output

1603
957
7161
9466
3232
5223
1879
1669
1282
0

HINT

 

 满足 n<=150000,Q<=200000。对于所有数据,满足 A<=10^9

 
题解
  其实就是动态点分治的模板题……但是如果是动态点分套线段树的话看起来会mle,于是我们可以开个数组对于每个子树按权值从小到大记录在当前子树里点的信息(是的我知道你们c++有vector不用那么麻烦),然后算个前缀和在上面二分查找一减就行了……
  其实还挺好写的……
技术分享
  1 program j01;
  2 const maxn=300086;
  3 var head:array[0..maxn]of longint;
  4     data:array[0..2*maxn]of int64;
  5     q,next:array[0..2*maxn]of longint;
  6     size,now,maxu:array[0..maxn]of longint;
  7     st:array[0..22,0..2*maxn]of longint;
  8     fa:array[0..maxn]of longint;
  9     dep:array[0..maxn]of int64;
 10     sum1,sum2:array[0..20*maxn]of int64;
 11     root,rosize,mnsize:longint;
 12     fir:array[0..maxn]of longint;
 13     vis:array[0..maxn]of boolean;
 14     bin:array[0..2*maxn]of longint;
 15     u,v,w,n,m,tt,aa,i,time,tot,j:longint;
 16     a,ps:array[0..maxn]of longint;
 17     line:array[0..20*maxn]of longint;
 18     bg,ed:array[0..maxn]of longint;
 19     ax,bx,ll,rr,ans:int64;
 20 
 21 
 22 function max(a,b:int64):int64;inline;begin if a>b then exit(a) else exit(b);end;
 23 function min(a,b:int64):int64;inline;begin if a<b then exit(a) else exit(b);end;
 24 
 25 procedure swap(var a,b:longint);
 26 var c:longint;
 27 begin
 28   c:=a;a:=b;b:=c;
 29 end;
 30 
 31 procedure addd(u,v,w:longint);
 32 begin
 33   inc(tt);q[tt]:=v;data[tt]:=w;next[tt]:=head[u];head[u]:=tt;
 34 end;
 35 
 36 procedure sort(l,r:longint);
 37 var i,j,x,y:longint;
 38 begin
 39   i:=l;j:=r;x:=a[ps[(i+j)div 2]];
 40   repeat
 41     while a[ps[i]]<x do inc(i);
 42     while x<a[ps[j]] do dec(j);
 43     if i<=j then
 44     begin
 45       swap(ps[i],ps[j]);
 46       inc(i);dec(j);
 47     end;
 48   until i>j;
 49   if i<r then sort(i,r);
 50   if l<j then sort(l,j);
 51 end;
 52 
 53 procedure dfsst(i,pre:longint);
 54 var j:longint;
 55 begin
 56   inc(time);fir[i]:=time;st[0,time]:=i;
 57   j:=head[i];
 58   while j>0 do
 59   begin
 60     if q[j]<>pre then
 61     begin
 62       dep[q[j]]:=dep[i]+data[j];dfsst(q[j],i);
 63       inc(time);st[0,time]:=i;
 64     end;
 65     j:=next[j];
 66   end;
 67 end;
 68 
 69 function min_st(a,b:longint):longint;
 70 begin
 71   if fir[a]<fir[b] then exit(a) else exit(b);
 72 end;
 73 
 74 procedure getst;
 75 var i,j:longint;
 76 begin
 77   bin[1]:=0;
 78   for i:=2 to time do
 79     if i and(i-1)=0 then bin[i]:=bin[i-1]+1 else bin[i]:=bin[i-1];
 80   for i:=1 to bin[time] do
 81     for j:=1 to time+1-(1 shl i) do
 82       st[i,j]:=min_st(st[i-1,j],st[i-1,j+(1 shl(i-1))]);
 83 end;
 84 
 85 function lca(u,v:longint):longint;
 86 var k:longint;
 87 begin
 88   u:=fir[u];v:=fir[v];if u>v then swap(u,v);k:=bin[v-u+1];
 89   exit(min_st(st[k,u],st[k,v+1-(1 shl k)]));
 90 end;
 91 
 92 function dist(u,v:longint):int64;
 93 begin
 94   exit(dep[u]+dep[v]-2*dep[lca(u,v)]);
 95 end;
 96 
 97 procedure dfssize(i,pre:longint);
 98 var j:longint;
 99 begin
100   size[i]:=1;maxu[i]:=0;j:=head[i];
101   while j>0 do
102   begin
103     if(vis[q[j]]=false)and(q[j]<>pre)then
104     begin
105       dfssize(q[j],i);inc(size[i],size[q[j]]);
106       maxu[i]:=max(maxu[i],size[q[j]]);
107     end;
108     j:=next[j];
109   end;
110 end;
111 
112 procedure dfsroot(i,pre:longint);
113 var j:longint;
114 begin
115   maxu[i]:=max(maxu[i],rosize-size[i]);
116   if maxu[i]<mnsize then begin root:=i;mnsize:=maxu[i]; end;
117   j:=head[i];
118   while j>0 do
119   begin
120     if(vis[q[j]]=false)and(q[j]<>pre)then dfsroot(q[j],i);
121     j:=next[j];
122   end;
123 end;
124 
125 procedure dfstree(i,pre:longint);
126 var j,ro:longint;
127 begin
128   dfssize(i,0);mnsize:=maxlongint;rosize:=size[i];
129   dfsroot(i,0);ro:=root;now[ro]:=tot;bg[ro]:=tot;tot:=tot+rosize;ed[ro]:=tot-1;
130   vis[ro]:=true;fa[ro]:=pre;
131   j:=head[ro];
132   while j>0 do
133   begin
134     if(vis[q[j]]=false)then dfstree(q[j],ro);
135     j:=next[j];
136   end;
137 end;
138 
139 procedure ins(x:longint);
140 var u,f:longint;d:int64;
141 begin
142   u:=x;sum1[now[u]]:=0;
143   while fa[u]<>0 do
144   begin
145     f:=fa[u];d:=dist(x,f);
146     sum1[now[f]]:=d;sum2[now[u]]:=d;
147     u:=f;
148   end;
149   u:=x;
150   while u>0 do
151   begin
152     line[now[u]]:=x;inc(now[u]);u:=fa[u];
153   end;
154 end;
155 
156 function finddown(l,r,x:longint):longint;
157 var mid:longint;
158 begin
159   if x<=a[line[l]] then exit(l-1);
160   while l<r do
161   begin
162     mid:=(l+r)div 2;
163     if a[line[mid+1]]>=x then r:=mid else l:=mid+1;
164   end;
165   exit(l);
166 end;
167 
168 function findup(l,r,x:longint):longint;
169 var mid:longint;
170 begin
171   if x<a[line[l]] then exit(l-1);
172   if x>=a[line[r]] then exit(r);
173   while l<r do
174   begin
175     mid:=(l+r)div 2;
176     if a[line[mid+1]]>x then r:=mid else l:=mid+1;
177   end;
178   exit(l);
179 end;
180 
181 procedure solve(x:longint);
182 var u,f,l,r,pl,pr:longint;d:int64;
183 begin
184   l:=finddown(bg[x],ed[x],ll);r:=findup(bg[x],ed[x],rr);
185   inc(ans,sum1[r]-sum1[l]);u:=x;pl:=l;pr:=r;
186   while fa[u]<>0 do
187   begin
188     f:=fa[u];d:=dist(x,f);
189     l:=finddown(bg[f],ed[f],ll);r:=findup(bg[f],ed[f],rr);
190     ans:=ans+sum1[r]-sum1[l]+d*(r-l);
191     ans:=ans-(sum2[pr]-sum2[pl])-d*(pr-pl);
192     u:=f;pl:=l;pr:=r;
193   end;
194 end;
195 
196 begin
197   readln(n,m,aa);
198   for i:=1 to n do begin read(a[i]);ps[i]:=i; end;
199   sort(1,n);
200   for i:=1 to n-1 do
201   begin
202     readln(u,v,w);addd(u,v,w);addd(v,u,w);
203   end;
204   dfsst(1,0);getst;
205   tot:=1;dfstree(1,0);
206   for i:=1 to n do ins(ps[i]);
207   for i:=1 to tot do
208   begin
209     inc(sum1[i],sum1[i-1]);inc(sum2[i],sum2[i-1]);
210   end;
211   for i:=1 to m do
212   begin
213     readln(u,ax,bx);
214     ll:=min((ax+ans)mod aa,(bx+ans)mod aa);
215     rr:=max((ax+ans)mod aa,(bx+ans)mod aa);
216     ans:=0;solve(u);writeln(ans);
217   end;
218 end.
View Code

 






























以上是关于bzoj4012: [HNOI2015]开店的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 4012 HNOI2015 开店

BZOJ 4012 HNOI2015 开店 树的边分治

[BZOJ4012][HNOI2015]开店

bzoj4012: [HNOI2015]开店

[BZOJ 4012][HNOI2015]开店(树链剖分+主席树)

bzoj4012[HNOI2015]开店 动态树分治+二分查找