题解:动态点分治

建立点分树

每个点维护点分树子树内节点到这个节点和父亲节点距离的前缀和

二分查找锁定合法区间

对每个祖先分治中心查询路径和然后减去不合法子树内的路径和

注意:求大量LCA时用树剖

不开O2时少用STL

相乘炸int

lower_bound和upper_bound返回值边界

注意常数

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn=200009;
const int oo=1000000000;
typedef long long Lint; int n,T,u;
int a[maxn]; int cntedge;
int head[maxn];
int to[maxn<<1],nex[maxn<<1],dist[maxn<<1];
void Addedge(int x,int y,int z){
nex[++cntedge]=head[x];
to[cntedge]=y;
dist[cntedge]=z;
head[x]=cntedge;
} int nowsiz,root;
int vis[maxn];
int siz[maxn],g[maxn];
void Getsiz(int x,int fa){
siz[x]=1;
for(int i=head[x];i;i=nex[i]){
if(vis[to[i]])continue;
if(to[i]==fa)continue;
Getsiz(to[i],x);
siz[x]+=siz[to[i]];
}
}
void Getroot(int x,int fa){
siz[x]=1;
g[x]=0;
for(int i=head[x];i;i=nex[i]){
if(vis[to[i]])continue;
if(to[i]==fa)continue;
Getroot(to[i],x);
siz[x]+=siz[to[i]];
g[x]=max(g[x],siz[to[i]]);
}
g[x]=max(g[x],nowsiz-siz[x]);
if(g[x]<g[root])root=x;
} int divfa[maxn];
void Sol(int x){
vis[x]=1;
Getsiz(x,0);
for(int i=head[x];i;i=nex[i]){
if(vis[to[i]])continue;
root=0;nowsiz=siz[to[i]];
Getroot(to[i],x);
divfa[root]=x;
Sol(root);
}
} int father[maxn],dep[maxn],d[maxn],top[maxn],hson[maxn];
void Dfs(int x,int fa){
father[x]=fa;
dep[x]=dep[fa]+1;
siz[x]=1;
for(int i=head[x];i;i=nex[i]){
if(to[i]==fa)continue;
d[to[i]]=d[x]+dist[i];
Dfs(to[i],x);
siz[x]+=siz[to[i]];
if(siz[to[i]]>siz[hson[x]])hson[x]=to[i];
}
}
void Dfs2(int x,int toppoint){
top[x]=toppoint;
if(!hson[x])return;
Dfs2(hson[x],toppoint);
for(int i=head[x];i;i=nex[i]){
if(to[i]==father[x])continue;
if(to[i]==hson[x])continue;
Dfs2(to[i],to[i]);
}
} int Getlca(int u,int v){
int tu=top[u];
int tv=top[v];
while(tu!=tv){
if(dep[tu]<dep[tv]){
swap(u,v);
swap(tu,tv);
}
u=father[tu];
tu=top[u];
}
if(dep[u]<dep[v])return u;
else return v;
} int Getdist(int x,int y){
if((x==0)||(y==0))return 0;
int lca=Getlca(x,y);
return d[x]+d[y]-d[lca]-d[lca];
} vector<int>G[maxn];
vector<Lint>S[maxn];
vector<Lint>S2[maxn]; int cmp(const int &rhs1,const int &rhs2){
return a[rhs1]<a[rhs2];
} int main(){
scanf("%d%d%d",&n,&T,&u);
for(int i=1;i<=n;++i)scanf("%d",&a[i]);
for(int i=1;i<n;++i){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
Addedge(x,y,z);
Addedge(y,x,z);
} Dfs(1,0);
Dfs2(1,1); g[0]=oo;root=0;nowsiz=n;
Getroot(1,0);
Sol(root); for(int i=1;i<=n;++i){
int x=i;
while(x){
G[x].push_back(i);
x=divfa[x];
}
} // for(int i=1;i<=n;++i){
// for(int j=1;j<=n;++j){
// cout<<Getdist(i,j)<<' ';
// }
// cout<<endl;
// }
for(int i=1;i<=n;++i){
sort(G[i].begin(),G[i].end(),cmp);
Lint now=0,now2=0;
for(int j=0;j<G[i].size();++j){
now=now+Getdist(i,G[i][j]);
now2=now2+Getdist(divfa[i],G[i][j]);
S[i].push_back(now);
S2[i].push_back(now2);
G[i][j]=a[G[i][j]];
}
// printf("=->%d %d %d\n",i,now,now2);
}
// for(int i=1;i<=n;++i)cout<<d[i]<<' ';
// cout<<endl;
Lint ans=0;
while(T--){
int x,y,Lold,Rold;
scanf("%d%d%d",&x,&Lold,&Rold);
y=x;
int t1=(Lold+ans)%u;
int t2=(Rold+ans)%u;
Lold=min(t1,t2);
Rold=max(t1,t2);
// cout<<Lold<<' '<<Rold<<endl;
ans=0;
int p=0;
// cout<<ans<<endl;
// for(int i=0;i<G[x].size();++i)cout<<G[x][i]<<' ';
// cout<<endl;
p=upper_bound(G[x].begin(),G[x].end(),Rold)-G[x].begin()-1;
if(p>-1)ans+=S[x][p];
// cout<<p<<endl;
p=lower_bound(G[x].begin(),G[x].end(),Lold)-G[x].begin();
if(p)ans-=S[x][p-1];
// cout<<p<<endl;
// cout<<ans<<endl;
while(divfa[x]){
Lint fdist=Getdist(divfa[x],y);
int fa=divfa[x]; p=upper_bound(G[fa].begin(),G[fa].end(),Rold)-G[fa].begin()-1;
if(p>-1)ans+=S[fa][p]+fdist*(p+1);
// cout<<p<<' ';
p=lower_bound(G[fa].begin(),G[fa].end(),Lold)-G[fa].begin();
if(p)ans-=S[fa][p-1]+fdist*p;
// cout<<p<<endl;
// cout<<ans<<endl;
p=upper_bound(G[x].begin(),G[x].end(),Rold)-G[x].begin()-1;
if(p>-1)ans-=S2[x][p]+fdist*(p+1);
p=lower_bound(G[x].begin(),G[x].end(),Lold)-G[x].begin();
if(p)ans+=S2[x][p-1]+fdist*p;
// cout<<ans<<endl;
x=divfa[x];
}
printf("%lld\n",ans);
}
return 0;
}

  

P3241 [HNOI2015]开店的更多相关文章

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

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

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

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

  3. luogu P3241 [HNOI2015]开店

    传送门 (下面记年龄为\(a_x\))题目要求的是\[\sum_{x=1}^{n} [a_x\in [l,r]]*dis(x,u)=\sum_{x=1}^{n} [a_x\in [l,r]]*de_x ...

  4. 并不对劲的bzoj4012:loj2116:p3241: [HNOI2015]开店

    题目大意 有一棵\(n\)(\(n\leq1.5*10^5\))个节点的二叉树,有点权\(x\),边权\(w\),\(q\)(\(q\leq2*10^5\))组询问,每组询问给出\(u,l,r\),求 ...

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

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

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

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

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

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

  8. BZOJ4012 [HNOI2015]开店

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

  9. bzoj 4012: [HNOI2015]开店

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

随机推荐

  1. Linux-10Year

    主流Linux发行版近10年排行曲线 10个主流的发行版概述(distrowatch挑选) 搜索特定的发行 选择建议     初级用户选择:开箱即用     中级用户组装:适合你自己的系统     高 ...

  2. 009-PHP循环输出数组成员

    <?php $Cities[] = "<B>北京</B>"; //等同于$Cities[0] = "北京" $Cities[] = ...

  3. Docker退出容器不关闭容器的方法

    进入docker容器后如果退出容器,容器就会变成Exited的状态,那么如何退出容器让容器不关闭呢? 如果要正常退出不关闭容器,请按Ctrl+P+Q进行退出容器,这一点很重要,请牢记! 以下示例为退出 ...

  4. 读取docx表格中的信息

    参考了 http://blog.csdn.net/qq_34475777/article/details/62055523 http://www.cnblogs.com/deepwaterplan/a ...

  5. 一百一十五、脱离SAP本体,通过ActiveX读取SAP表中数据

    一.Sap自带有客户端,但是非常之臃肿卡顿,可以利用ActiveX的方式,脱离Sap本体,来读取Sap表中的内容进行插入等操作,非常之方便.代码如下: 二.界面如下,输入好相关内容,点击登录,提示登录 ...

  6. 096-PHP循环使用next取数组元素

    <?php function return_item($arr,$num=0){ //定义函数 for($i=0;$i<$num;$i++){ //循环向前移动数组指针 next($arr ...

  7. ZOJ 3791 An easy game DP+组合数

    给定两个01序列,每次操作可以任意改变其中的m个数字 0变 1  1 变 0,正好要变化k次,问有多少种变法 dp模型为dp[i][j],表示进行到第i次变化,A,B序列有j个不同的 变法总和. 循环 ...

  8. Flink Window窗口机制

    总览 Window 是flink处理无限流的核心,Windows将流拆分为有限大小的"桶",我们可以在其上应用计算. Flink 认为 Batch 是 Streaming 的一个特 ...

  9. NASA的10条编码规则

    关于NASA的10条编程规则,他们曾表示:这些规则的作用就像汽车上的安全带:最初,它们可能有点不舒服,但过了一会儿,它们的使用就变成了第二天性,而没有使用它们就变得不可想象. Gerard J. Ho ...

  10. Docker 搭建开源 CMDB平台 “OpsManage” 之 Redis

    整体结构如下图   先来在 172.16.0.200 安装docker-ce (新)或 docker-io(旧)      0: Docker-ce  (新版本  Docker version 17. ...