正题
题目链接:https://gmoj.net/senior/#main/show/5699
题目大意
一棵树,每个节点有权值,每天所有权值会往它的父节点滑一位,然后有操作会在某一天的某个节点加权值。
然后询问若干次某个时间一个位置的子树权值和。
解题思路
因为每次滑一位,所以我们直接把深度带到时间里,也就是带入t+depxt+dep_xt+depx。
这样就可以只看时间了,那么对于一个询问(t1,x1)(t_1,x_1)(t1,x1),会被修改(t2,x2,w)(t_2,x_2,w)(t2,x2,w)影响当且仅当。t2≤t1且t1+depx1≥t2+depx2t_2\leq t_1且t_1+dep_{x_1}\geq t_2+dep_{x_2}t2≤t1且t1+depx1≥t2+depx2
然后树套树做即可。
时间复杂度O((n+q)log2n)O((n+q)\log^2 n)O((n+q)log2n)
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
#define lowbit(x) (x&-x)
using namespace std;
const int N=2e5+10;
struct enode{int to,next;
}a[N];
struct qnode{int t,x,w;
}q[N*2];
int n,m,T,cnt,num,tot,ls[N],rfn[N],ed[N],rt[N],dep[N];
ll ans[N];
struct Seg_Tree{int cnt,ls[N<<6],rs[N<<6];ll val[N<<6];void Change(int &x,int l,int r,int pos,int w){if(!x)x=++cnt;if(l==r){val[x]+=w;return;}int mid=(l+r)>>1;if(pos<=mid)Change(ls[x],l,mid,pos,w);else Change(rs[x],mid+1,r,pos,w);val[x]=val[ls[x]]+val[rs[x]];return;}ll Ask(int x,int L,int R,int l,int r){if(!x)return 0;if(L==l&&R==r)return val[x];int mid=(L+R)>>1;if(r<=mid)return Ask(ls[x],L,mid,l,r);if(l>mid)return Ask(rs[x],mid+1,R,l,r);return Ask(ls[x],L,mid,l,mid)+Ask(rs[x],mid+1,R,mid+1,r);}
}Tr;
void Change(int x,int pos,int val){x=N-x;while(x<N){Tr.Change(rt[x],1,n,pos,val);x+=lowbit(x);}return;
}
ll Ask(int x,int l,int r){ll ans=0;x=N-x;while(x){ans+=Tr.Ask(rt[x],1,n,l,r);x-=lowbit(x);}return ans;
}
void addl(int x,int y){a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;return;
}
void dfs(int x,int fa){rfn[x]=++num;dep[x]=dep[fa]+1;for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(y==fa)continue;dfs(y,x);}ed[x]=num;
}
bool cmp(qnode x,qnode y){if(x.t==y.t)return x.w<y.w;return x.t<y.t;
}
int main()
{freopen("appletree.in","r",stdin);freopen("appletree.out","w",stdout);scanf("%d%d%d",&n,&m,&T);for(int i=1;i<=n;i++){int w;scanf("%d",&w);q[++cnt]=(qnode){0,i,w};}for(int i=1;i<n;i++){int x,y;scanf("%d%d",&x,&y);addl(x,y);addl(y,x);}dfs(1,1);for(int i=1;i<=m;i++){int t,x,w;scanf("%d%d%d",&t,&x,&w);q[++cnt]=(qnode){t,x,w};}for(int i=1;i<=T;i++){int t,x;scanf("%d%d",&t,&x);q[++cnt]=(qnode){t,x,-i};}sort(q+1,q+1+cnt,cmp);for(int i=1;i<=cnt;i++){if(q[i].w<0)ans[-q[i].w]=Ask(q[i].t+dep[q[i].x]-1,rfn[q[i].x],ed[q[i].x]); else Change(q[i].t+dep[q[i].x],rfn[q[i].x],q[i].w);}for(int i=1;i<=T;i++)printf("%lld\n",ans[i]);
}