题目分析:

  观察题目发现度数不小于三,考虑从边分治入手,用点分治代替。将树划分成重心链接的结构,称为点分树。令当前询问的点为$ u $。那么我们考虑点分树的根到$ u $的一条路径。考虑根结点,排除掉与$ u $有关的点所在的子树,剩下的点到$ u $的路径长度等价于它们到根的路径加上根到$ u $的路径。所以我们要做的是消去$ u $所在子树的影响,然后递归问题。这个做法在点分治意义下是常用做法,前缀和维护即可。由于每个点都在点分路径上的前缀和上出现了一次,而点分树高为$ O(\log n) $,所以空间为$ O(n*\log n) $。时间是$ O(n*\log^2n) $

代码:

 #include<bits/stdc++.h>
using namespace std; const int maxn = ; int n,Q,A; int x[maxn]; vector <pair<int,int> > g[maxn];
int euler[maxn<<],nE,app[maxn][];
int RMQ[maxn<<][],f[maxn],dep[maxn],climb[maxn]; template<typename T>
void in(T &x){
x = ; char ch = getchar();
while(ch > '' || ch < '') ch = getchar();
while(ch >= '' && ch <= '') x = x*+ch-'',ch=getchar();
} void dfs(int now,int last,int dp,int cl){
dep[now] = dp; f[now] = last; climb[now] = cl;
euler[++nE] = now; app[now][] = app[now][] = nE;
for(int i=;i<g[now].size();i++){
int pp = g[now][i].first,len = g[now][i].second;
if(pp == last) continue;
dfs(pp,now,dp+len,cl+);
euler[++nE] = now; app[now][] = nE;
}
} void BuildRMQ(){
for(int i=;i<=nE;i++) RMQ[i][] = euler[i];
for(int k=;(<<k)<=nE;k++){
for(int i=;i<=nE;i++){
if(i+(<<k-) > nE) {RMQ[i][k] = RMQ[i][k-];continue;}
if(climb[RMQ[i][k-]] < climb[RMQ[i+(<<k-)][k-]]){
RMQ[i][k] = RMQ[i][k-];
}else RMQ[i][k] = RMQ[i+(<<k-)][k-];
}
}
} int QueryLCA(int u,int v){
int fst = min(app[u][],app[v][]),sec = max(app[u][],app[v][]);
int len = sec-fst+,k = ;
while((<<k+) <= len) k++;
if(climb[RMQ[fst][k]] < climb[RMQ[sec-(<<k)+][k]]) return RMQ[fst][k];
else return RMQ[sec-(<<k)+][k];
} int dist(int u,int v){ return dep[u]+dep[v]-*dep[QueryLCA(u,v)]; } class Pdivide{
private:
int sz[maxn],arr[maxn],seg[maxn],fa[maxn];
vector <pair<int,int> > v[maxn],v2[maxn];
vector <long long> sum[maxn],sum2[maxn];
stack <int> sta;
void GetSize(int now,int last){
sz[now] = ;seg[now] = ;
for(int i=;i<g[now].size();i++){
int pp = g[now][i].first;
if(arr[pp] || pp == last) continue;
GetSize(pp,now);
sz[now] += sz[pp];
seg[now] = max(seg[now],sz[pp]);
}
sz[now]++;
}
int GetG(int now,int last,int tot){
int res = now; seg[now] = max(seg[now],tot-sz[now]-);
for(int i=;i<g[now].size();i++){
int pp = g[now][i].first;
if(arr[pp] || pp == last) continue;
int p = GetG(pp,now,tot);
if(seg[p] < seg[res]) res = p;
}
return res;
}
void LenQuery(int now,int last,int dst,int root,int oldroot){
v[root].push_back(make_pair(x[now],dst));
if(oldroot != ) v2[root].push_back(make_pair(x[now],dist(now,oldroot)));
for(int i=;i<g[now].size();i++){
int pp = g[now][i].first, len = g[now][i].second;
if(arr[pp] || pp == last) continue;
LenQuery(pp,now,dst+len,root,oldroot);
}
}
void divide(int now,int last,int ht){
GetSize(now,);
int p = GetG(now,,sz[now]); LenQuery(p,,,p,last); sort(v[p].begin(),v[p].end()); sum[p].push_back();
sort(v2[p].begin(),v2[p].end()); sum2[p].push_back();
for(int i=;i<v[p].size();i++) sum[p].push_back(sum[p][i]+1ll*v[p][i].second);
for(int i=;i<v2[p].size();i++) sum2[p].push_back(sum2[p][i]+1ll*v2[p][i].second); fa[p] = last;arr[p] = ht;
for(int i=;i<g[p].size();i++){
int nxt = g[p][i].first;
if(arr[nxt]) continue;
divide(nxt,p,ht+);
}
} public:
void BuildTree(){divide(,,);}
void printans(int now,int l,int r,long long &lastans){
int p = now;
while(p != ) sta.push(p),p = fa[p];
long long ans = ;
while(!sta.empty()){
int tp = sta.top();sta.pop();
int pp = lower_bound(v[tp].begin(),v[tp].end(),make_pair(l,))-v[tp].begin();
if(pp == v[tp].size()||v[tp][pp].first > r) break;
int ed = upper_bound(v[tp].begin(),v[tp].end(),make_pair(r,(int)1E9))-v[tp].begin()-;
int len = ed-pp+;
ans += sum[tp][ed+] - sum[tp][pp] + 1ll*len*dist(tp,now);
if(fa[tp]!=)
ans -= (sum2[tp][ed+] - sum2[tp][pp] + 1ll*len*dist(fa[tp],now));
}
while(!sta.empty())sta.pop();
printf("%lld\n",ans);lastans = ans;
}
}T1; void init(){
dfs(,,,);
BuildRMQ();
T1.BuildTree();
} void work(){
long long lastans = ;
for(int i=;i<=Q;i++){
int a,u,v; in(a),in(u),in(v);
u = (1ll*u+lastans)%A;
v = (1ll*v+lastans)%A;
if(u > v) swap(u,v);
T1.printans(a,u,v,lastans);
}
} int main(){
in(n),in(Q),in(A);
for(int i=;i<=n;i++) in(x[i]);
for(int i=;i<n;i++){
int u,v,w; in(u),in(v),in(w);
g[u].push_back(make_pair(v,w));
g[v].push_back(make_pair(u,w));
}
init();
work();
return ;
}

LOJ2116 [HNOI2015] 开店 【点分治】的更多相关文章

  1. BZOJ 4012 [HNOI2015]开店 (树分治+二分)

    题目大意: 给你一棵树,边有边权,点有点权,有很多次询问,求点权$\in[l,r]$的所有节点到某点$x$的距离之和,强制在线 感觉这个题应该放在动态点分之前做= = 套路方法和动态点分是一样的 每次 ...

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

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

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

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

  4. 洛谷 P3241 [HNOI2015]开店 解题报告

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

  5. [HNOI2015]开店 树链剖分,主席树

    [HNOI2015]开店 LG传送门 蒟蒻表示不会动态淀粉质. 先把点按年龄排序, 设\(dis[i]\)表示\(i\)到根的距离. 把我们要算的东西稍微变下形:\(ans\) \[ = \sum \ ...

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

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

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

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

  8. BZOJ4012 [HNOI2015]开店 (动态点分治)

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

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

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

随机推荐

  1. C# Type.GetType 返回NULL 问题解决记录

    Type.GetType("OP.Client.Html.Resources.KenFengFormMethod"); 从Dll里面获取KenFengFormMethod这个会返回 ...

  2. Windows Community Toolkit 4.0 - DataGrid - Overview

    概述 Windows Community Toolkit 4.0 于 2018 月 8 月初发布:Windows Community Toolkit 4.0 Release Note. 4.0 版本相 ...

  3. Linux 下RPM打包制作流程

    原文地址:https://www.cnblogs.com/postgres/p/5726339.html 开始前的准备 安装rpmbuild软件包 yum -y install rpm-build 生 ...

  4. Python_%---format_43

    fat39 博客园 首页 新随笔 联系 订阅 管理 随笔 - 142  文章 - 0  评论 - 0 python基础_格式化输出(%用法和format用法)   目录 %用法 format用法 %用 ...

  5. CodeForces - 1051D-简单DP

    这个题叫问给一个2*N的方块,你可以在每一个上填任意黑或者白两种,假设颜色相同的并且有公共边的就被认为是一块,问组成K块有多少种方案. 这题开始感觉无从下手,像组合数学又不像的,其实这个题的关键在于, ...

  6. codeforces#766 D. Mahmoud and a Dictionary (并查集)

    题意:给出n个单词,m条关系,q个询问,每个对应关系有,a和b是同义词,a和b是反义词,如果对应关系无法成立就输出no,并且忽视这个关系,如果可以成立则加入这个约束,并且输出yes.每次询问两个单词的 ...

  7. hdu 4135 a到b的范围中多少数与n互质(容斥)

    Co-prime 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4135 input The first line on input contains ...

  8. openstack-KVM-存储配置

    一.块存储设备 1.存储设备类型 IDE SCSI 软盘 U盘 virtio磁盘(KVM使用类型) 2.查看存储设备 lspci | grep IDE lspci | grep SCSI lspci ...

  9. js基础语法之函数

    普通函数 function foo(a, b){ return a + b; } foo(10, 20) >>> 30 匿名函数 var f = function(){console ...

  10. mysql-SQL Error: 1205, SQLState: 41000

    mysql-SQL Error: 1205, SQLState: 41000——CSDN问答频道https://ask.csdn.net/questions/176492 mysql-SQL Erro ...