题解:动态点分治

建立点分树

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

二分查找锁定合法区间

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

注意:求大量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. Day5-T1

    原题目 小月言要过四岁生日了,她的妈妈为她准备了n根火腿,她想将这些火腿均分给m位小朋友,所以她可能需要切火腿.为了省事,小月言想切最少的刀数,使这n根火腿分成均等的m份.请问最少要切几刀? 第一行一 ...

  2. 剑指offer 链表中环的入口位置

    题目描述 一个链表中包含环,请找出该链表的环的入口结点.   思路:这题需要知道a = c,然后head和slow每次走一步,相遇的时候就是第一个入口交点, 注意:for循环或者while循环之后,一 ...

  3. Java中数组的创建

    Java中数组的使用 1.普通数组变量的定义: //数组 //1.数组是Java中很重要的一部分,今天对数组进行了大致的了解,Java中的数组和C中数组还是有一定的区别的 //以下是总结的几种方法 p ...

  4. 配置vSphere Web Client超时值

    1.默认超时值120分钟 2.webclient.properties文件位置:     Windows系统:C:\ProgramData\VMware\vCenterServer\cfg\vsphe ...

  5. netty权威指南学习笔记一——NIO入门(2)伪异步IO

    在上一节我们介绍了四种IO相关编程的各个特点,并通过代码进行复习了传统的网络编程代码,伪异步主要是引用了线程池,对BIO中服务端进行了相应的改造优化,线程池的引入,使得我们在应对大量客户端请求的时候不 ...

  6. USB Windows驱动 音频解决方案芯片DP108

    DP108是一款完全替代CM108的高度集成的单芯片USB音频解决方案芯片.方便的USB即插即用的兼容性,用户可以快速创建易用性,高质量和便携式USB音频产品基于高度集成的单芯片解决方案.所有重要的模 ...

  7. CSS - 美化字体 => CSS的-font-smoothin属性优化

    body{     margin: 0;     font-family: Arial, Helvetica, sans-serif;     line-height: 1.2em;     back ...

  8. JS - 获取数组中的最后1个

    arr = [1,2,3,4,5] console.log(arr[arr.length-1])    //输出的为5,即最后一个

  9. docker 后台运行和进入后台运行的容器

    先创建并进入一个新的被命名为newos的新容器    docker run -it --name newos docker.io/centos #创建并指定端口号映射 docker run -d -p ...

  10. [LeetCode] 929. Unique Email Addresses 独特的邮件地址

    Every email consists of a local name and a domain name, separated by the @ sign. For example, in ali ...