Description
给一棵树,Q次询问颜色在[L,R]之间的点到x的距离之和,强制在线
n
≤
1.5
×
1
0
5
,
Q
≤
2
×
1
0
5
n\le1.5\times10^5,Q\le2\times10^5
n≤1.5×105,Q≤2×105
Solution
带修改的话就是树套树,这里不用修改就可持久化就好了
说一下这里标记永久化的做法吧
对于一个修改区间[l,r],如果它完全包含了当前线段区间[tl,tr],那么我们就把标记打在这个位置
如果[tl,tr]完全包含了[l,r],那么我们就把[l,r]的贡献加在这个位置的区间和里面
然后就没了
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define lowbit(x) (x&-x)
#define fi first
#define se second
typedef long long LL;
typedef std:: pair <int,LL> pair;
const int N=200005;
struct edge {int y,w,next;} e[N*2];
struct treeNode {int l,r,tag; LL sum;} t[N*205];
pair p[N],s[N];
int dis[N],ls[N],rt[N],a[N],b[N],edCnt,tot;
int size[N],pos[N],fa[N],bl[N];
LL sum[N];
pair operator +(pair a,pair b) {
return pair(a.fi+b.fi,a.se+b.se);
}
pair operator -(pair a,pair b) {
return pair(a.fi-b.fi,a.se-b.se);
}
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):v,ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
void add_edge(int x,int y,int w) {
e[++edCnt]=(edge) {y,w,ls[x]}; ls[x]=edCnt;
e[++edCnt]=(edge) {x,w,ls[y]}; ls[y]=edCnt;
}
void modify(int &now,int pre,int tl,int tr,int l,int r) {
t[now=++tot]=t[pre];
if (tl>=l&&tr<=r) return (void) (t[now].tag++);
t[now].sum+=sum[r]-sum[l-1];
int mid=(tl+tr)>>1;
if (r<=mid) modify(t[now].l,t[pre].l,tl,mid,l,r);
else if (l>mid) modify(t[now].r,t[pre].r,mid+1,tr,l,r);
else {
modify(t[now].l,t[pre].l,tl,mid,l,mid);
modify(t[now].r,t[pre].r,mid+1,tr,mid+1,r);
}
}
LL query(int now,int tl,int tr,int l,int r) {
LL res=t[now].tag*(sum[r]-sum[l-1]);
if (tl>=l&&tr<=r) return res+t[now].sum;
int mid=(tl+tr)>>1;
if (r<=mid) res+=query(t[now].l,tl,mid,l,r);
else if (l>mid) res+=query(t[now].r,mid+1,tr,l,r);
else res+=query(t[now].l,tl,mid,l,mid)+query(t[now].r,mid+1,tr,mid+1,r);
return res;
}
void change(int x,int p) {
for (;x;x=fa[bl[x]]) {
modify(rt[p],rt[p],1,pos[0],pos[bl[x]],pos[x]);
}
}
LL ask(int x,int p) {
LL res=0;
for (;x;x=fa[bl[x]]) {
res+=query(rt[p],1,pos[0],pos[bl[x]],pos[x]);
}
return res;
}
void dfs1(int x) {
size[x]=1;
for (int i=ls[x];i;i=e[i].next) {
if (e[i].y==fa[x]) continue;
dis[e[i].y]=dis[x]+e[i].w; fa[e[i].y]=x;
dfs1(e[i].y); size[x]+=size[e[i].y];
}
}
void dfs2(int x,int up,int d) {
int mx=0,w; pos[x]=++pos[0];
sum[pos[x]]=sum[pos[x]-1]+d; bl[x]=up;
for (int i=ls[x];i;i=e[i].next) {
if (e[i].y!=fa[x]&&size[e[i].y]>size[mx]) mx=e[i].y,w=e[i].w;
}
if (!mx) return ;
dfs2(mx,up,w);
for (int i=ls[x];i;i=e[i].next) {
if (e[i].y!=fa[x]&&e[i].y!=mx) dfs2(e[i].y,e[i].y,e[i].w);
}
}
void add(int x,int v) {
for (;x<=pos[0];x+=lowbit(x)) s[x].fi++,s[x].se+=v;
}
pair get(int x) {
pair res=pair(0,0);
for (;x;x-=lowbit(x)) res=res+s[x];
return res;
}
int main(void) {
freopen("data.in","r",stdin);
int n=read(),Q=read(),A=read();
rep(i,1,n) a[i]=b[i]=read();
std:: sort(b+1,b+n+1);
int size=std:: unique(b+1,b+n+1)-b-1;
rep(i,1,n) {
a[i]=std:: lower_bound(b+1,b+size+1,a[i])-b;
p[i]=pair(a[i],i);
}
std:: sort(p+1,p+n+1);
rep(i,2,n) {
int x=read(),y=read(),w=read();
add_edge(x,y,w);
}
dfs1(1); dfs2(1,1,0);
rep(i,1,n) {
int x=p[i].se;
if (p[i-1].fi!=p[i].fi) rt[a[x]]=rt[p[i-1].fi];
change(x,p[i].fi);
add(p[i].fi,dis[x]);
}
LL lastans=0;
for (int x,l,r;Q--;) {
x=read(),l=read(),r=read();
l=(l+lastans)%A,r=(r+lastans)%A;
if (r<l) std:: swap(l,r);
r=std:: upper_bound(b+1,b+size+1,r)-b-1;
l=std:: upper_bound(b+1,b+size+1,l-1)-b-1;
pair tmp=get(r)-get(l);
LL res=1LL*dis[x]*tmp.fi+tmp.se;
LL wjp=ask(x,r)-ask(x,l);
printf("%lld\n", lastans=res-2*wjp);
}
return 0;
}