Description

风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到

人生哲学。最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱。这样的
想法当然非常好啦,但是她们也发现她们面临着一个问题,那就是店开在哪里,面
向什么样的人群。很神奇的是,幻想乡的地图是一个树形结构,幻想乡一共有 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

题解

  这题正解是动态点分治(不过据说主席树+树链剖分跑得更快?)

  如果不知道什么是动态点分的可以去看看幻想乡的战略游戏->蒟蒻的题解

  这一道题,我们考虑对于每一个点分树上的点维护什么。我们记录三个值,$sz_0$表示子树内的点数之和,$sz_1$表示子树内所有点到其的距离之和,$sz_2$表示子树内所有点到其父亲的距离之和。那么考虑我们在跳点分树的时候要如何维护答案呢?很明显$sz_1[u]+\sum sz_1[fa]-sz_2[p]+(sz_0[fa]-sz_0[p])*dist(fa,u)$就是在点分树上与$u$的$LCA$是$fa$的所有点的距离之和,其中$fa$为$p$的父亲,$p$为从$u$不断跳父亲直到根,那么只要不断枚举$fa$,并不断往上跳并维护答案就可以了。

  然而上面只是为了方便理解,因为具体的计算不是这样的。我们对于$u$点内部的贡献可以直接计算,然后考虑往上跳。在上述的式子中如果一个点$p$有$fa$,那么答案就要减去$sz_0[p]*dist(fa,u)+sz_2[p]$,如果一个点不是$u$那么答案就要加上$sz_0[p]+dist(p,u)$,然后每一个点都要加上自己的$sz_1$。按这个规律在跳点分树的时候不断加就好了

  然后考虑怎么在$[l,r]$之内,很明显可以搞一个差分,把每一个节点在点分树上的子树内的所有年龄的距离之和加起来,在做前缀和,那么在年龄$[l,r]$的人数就是$[1,r]-[1,l-1]$

  1. //minamoto
  2. #include<cstdio>
  3. #include<iostream>
  4. #include<cstring>
  5. #include<vector>
  6. #include<algorithm>
  7. #define ll long long
  8. #define N 150005
  9. using namespace std;
  10. #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
  11. char buf[<<],*p1=buf,*p2=buf;
  12. template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,:;}
  13. inline int read(){
  14. #define num ch-'0'
  15. char ch;bool flag=;int res;
  16. while(!isdigit(ch=getc()))
  17. (ch=='-')&&(flag=true);
  18. for(res=num;isdigit(ch=getc());res=res*+num);
  19. (flag)&&(res=-res);
  20. #undef num
  21. return res;
  22. }
  23. char sr[<<],z[];int C=-,Z;
  24. inline void Ot(){fwrite(sr,,C+,stdout),C=-;}
  25. inline void print(ll x){
  26. if(C><<)Ot();if(x<)sr[++C]=,x=-x;
  27. while(z[++Z]=x%+,x/=);
  28. while(sr[++C]=z[Z],--Z);sr[++C]='\n';
  29. }
  30. int head[N],Next[N<<],ver[N<<],edge[N<<];
  31. int n,tot,val[N],q,maxn;
  32. int st[N<<][],d[N],dfn[N],num,bin[],tp,logn[N<<];
  33. inline void add(int u,int v,int e){
  34. ver[++tot]=v,Next[tot]=head[u],head[u]=tot,edge[tot]=e;
  35. ver[++tot]=u,Next[tot]=head[v],head[v]=tot,edge[tot]=e;
  36. }
  37. inline void ST(){
  38. for(int j=;j<=tp;++j)
  39. for(int i=;i+bin[j]-<=(n<<);++i)
  40. st[i][j]=min(st[i][j-],st[i+bin[j-]][j-]);
  41. }
  42. void dfs1(int u,int fa){
  43. st[dfn[u]=++num][]=d[u];
  44. for(int i=head[u];i;i=Next[i]){
  45. int v=ver[i];
  46. if(v==fa) continue;
  47. d[v]=d[u]+edge[i],dfs1(v,u),st[++num][]=d[u];
  48. }
  49. }
  50. int fa[N],sz[N],son[N],size,rt;bool vis[N];
  51. void dfs2(int u,int fa){
  52. sz[u]=,son[u]=;
  53. for(int i=head[u];i;i=Next[i]){
  54. int v=ver[i];
  55. if(vis[v]||v==fa) continue;
  56. dfs2(v,u),sz[u]+=sz[v],cmax(son[u],sz[v]);
  57. }
  58. cmax(son[u],size-sz[u]);
  59. if(son[u]<son[rt]) rt=u;
  60. }
  61. inline ll dis(int a,int b){
  62. if(dfn[a]>dfn[b]) a^=b^=a^=b;
  63. int k=logn[dfn[b]-dfn[a]+];
  64. return d[a]+d[b]-(min(st[dfn[a]][k],st[dfn[b]-bin[k]+][k])<<);
  65. }
  66. struct node{
  67. int val;ll sz[];
  68. node(int a=,ll b=,ll c=,ll d=){val=a,sz[]=b,sz[]=c,sz[]=d;}
  69. inline bool operator <(const node &b)const
  70. {return val<b.val;}
  71. };
  72. vector<node> sta[N];
  73. void dfs3(int u,int f,int rt){
  74. sta[rt].push_back(node(val[u],,dis(u,rt),fa[rt]?dis(u,fa[rt]):));
  75. for(int i=head[u];i;i=Next[i]){
  76. int v=ver[i];
  77. if(v==f||vis[v]) continue;
  78. dfs3(v,u,rt);
  79. }
  80. }
  81. void dfs4(int u){
  82. vis[u]=true;
  83. dfs3(u,,u);sta[u].push_back(node(-,,,));
  84. sort(sta[u].begin(),sta[u].end());
  85. for(int i=,j=sta[u].size();i<j-;++i)
  86. sta[u][i+].sz[]+=sta[u][i].sz[],
  87. sta[u][i+].sz[]+=sta[u][i].sz[],
  88. sta[u][i+].sz[]+=sta[u][i].sz[];
  89. for(int i=head[u];i;i=Next[i]){
  90. int v=ver[i];
  91. if(vis[v]) continue;
  92. rt=,size=sz[v];
  93. dfs2(v,),fa[rt]=u,dfs4(rt);
  94. }
  95. }
  96. inline node query(int id,int l,int r){
  97. if(id==) return node();
  98. vector<node>::iterator it1=upper_bound(sta[id].begin(),sta[id].end(),node(r,,,));--it1;
  99. vector<node>::iterator it2=upper_bound(sta[id].begin(),sta[id].end(),node(l-,,,));--it2;
  100. return node(,it1->sz[]-it2->sz[],it1->sz[]-it2->sz[],it1->sz[]-it2->sz[]);
  101. }
  102. inline ll calc(int u,int l,int r){
  103. ll res=;
  104. for(int p=u;p;p=fa[p]){
  105. node a=query(p,l,r);
  106. res+=a.sz[];
  107. if(p!=u) res+=a.sz[]*dis(p,u);
  108. if(fa[p]) res-=a.sz[]+a.sz[]*dis(fa[p],u);
  109. }
  110. return res;
  111. }
  112. int main(){
  113. ll ans=;
  114. n=read(),q=read(),maxn=read();
  115. bin[]=,logn[]=-;
  116. for(int i=;i<=;++i) bin[i]=bin[i-]<<;
  117. while(bin[tp+]<=(n<<)) ++tp;
  118. for(int i=;i<=(n<<);++i) logn[i]=logn[i>>]+;
  119. for(int i=;i<=n;++i) val[i]=read();
  120. for(int i=;i<n;++i){
  121. int u=read(),v=read(),e=read();
  122. add(u,v,e);
  123. }
  124. dfs1(,),ST();
  125. rt=,son[]=n+,size=n,dfs2(,);
  126. dfs4(rt);
  127. while(q--){
  128. int a=read(),b=read(),c=read();
  129. b=(b+ans)%maxn,c=(c+ans)%maxn;
  130. if(b>c) b^=c^=b^=c;
  131. print(ans=calc(a,b,c));
  132. }
  133. Ot();
  134. return ;
  135. }

BZOJ4012 [HNOI2015]开店 (动态点分治)的更多相关文章

  1. [BZOJ4012][HNOI2015]开店(动态点分治,树链剖分)

    4012: [HNOI2015]开店 Time Limit: 70 Sec  Memory Limit: 512 MBSubmit: 2168  Solved: 947[Submit][Status] ...

  2. 【bzoj4012】[HNOI2015]开店 动态点分治+STL-vector

    题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的想法当然非常好啦,但是她们也发现她们面临着一个问题 ...

  3. 【BZOJ4012】[HNOI2015]开店 动态树分治+二分

    [BZOJ4012][HNOI2015]开店 Description 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点 ...

  4. P3241 [HNOI2015]开店 动态点分治

    \(\color{#0066ff}{ 题目描述 }\) 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱. 这样的想 ...

  5. luogu 3241 [HNOI2015]开店 动态点分治+二分+vector

    独立写出来+想出来的,1.5h就切了~ 建立点分树,然后用 $vector$ 暴力存所有子节点,然后二分一下子就可以了. #include <cstdio> #include <ve ...

  6. BZOJ4012[HNOI2015]开店——树链剖分+可持久化线段树/动态点分治+vector

    题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现她们面临着一个 ...

  7. BZOJ4012: [HNOI2015]开店【动态点分治】

    Description 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现 ...

  8. [loj2116]「HNOI2015」开店 动态点分治

    4012: [HNOI2015]开店 Time Limit: 70 Sec  Memory Limit: 512 MBSubmit: 2452  Solved: 1089[Submit][Status ...

  9. BZOJ4012 [HNOI2015]开店

    Description 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现 ...

随机推荐

  1. sudo免密码

    很多都是修改/etc/sudoers权限为740再加上一句 ALL=NOPASSWD:ALL 或者加一句 yourname ALL=(ALL) NOPASSWD: ALL 然后权限改回440 先说第一 ...

  2. App登录状态维持

    转载地址:http://www.jianshu.com/p/4b6b04244773 目前APP大都支持长登录,就是用户登录一次后,如果用户没有主动注销.清除APP缓存数据或卸载APP,就在一段时间内 ...

  3. log.error(msg)和log.error(msg,e)的显示区别

    log.error(msg): [2017-10-18 11:31:07,652] [Thread-7] (CmsCtlDataUploadFileExchange.java:50) ERROR co ...

  4. springmvc 类型转换器 数据回显及提示信息

    处理器的写法: 类型转换器的写法: 类型转换器在springmvc.xml中的配置如下: index.jsp的写法:

  5. spring security+cas(cas proxy配置)

    什么时候会用到代理proxy模式? 举一个例子:有两个应用App1和App2,它们都是受Cas服务器保护的,即请求它们时都需要通过Cas 服务器的认证.现在需要在App1中通过Http请求访问App2 ...

  6. clr相关名词

    程序集:一个或多个类型定义文件和资源文件的集合 Native Code(本机代码): 已被编译为特定于处理器的机器码的代码. 本地代码(native code)是计算机编程(代码),编译用来运行一个特 ...

  7. acoj-1735 输油管道 【中位数】

    题目链接:http://acdream.info/problem?pid=1735 输油管道 Time Limit: 2000/1000MS (Java/Others) Memory Limit: 2 ...

  8. jQuery的表单选择器

    1.常规选择器选择表单标签 $(function () { // var a = $("input").eq(0).val() // alert(a) // // var b = ...

  9. 技术讨论]mongodb驱动的正确使用方法

    原文地址:http://cnodejs.org/topic/5190d61263e9f8a542acd83b mongo数据库在nodejs平台有2个常用驱动,mongodb和mongoose,mon ...

  10. asp.net安装指令

    cd \ cd C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319aspnet_regiis.exe -i注册.NET4到IIS