题意:
一个树,对其有两个操作,操作1是将节点a的权值增加x
操作2是查询节点a到根节点R的简单路径上所有节点的权值的平方的和
答案对2^取模
题解:
如果ull类型的整数溢出了,就相当于取模2^64了。因为ull的范围是[0,2^64-1],所以直接开unsigned long long就行
有两个方法:
1.树链剖分单点修改,树链查询,时间复杂度为O(nlognlogn)
2.修改一个点x,该点的影响范围为其子树中所有点,因为子树的点到树根必经过x点。我dfs序上建立线段树,每个点维护当前点到根节点的答案,修改某个点的权值时,只需要对以当前点为根的子树进行修改即可。
查询时单点查询,时间复杂度为O(n * logn)
树链剖分好久没用了,比赛时敲模板一直在报错。。。
第二个方法还是挺直接的,dfs先构造父子关系以及深度,然后线段树维护即可
代码:
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<vector>
#include<map>
#define int long long
using namespace std;
unsigned long long val[1000009];
unsigned long long reval[1000009];
int in[1000009];
int out[1000009];
int inout[2000009];
vector<int>maps[1000009];
int cnt=1;
unsigned long long tree[8000009];
void dfs(int now,int pre,unsigned long long cc)//dfs序,顺便记录每个节点的价值和
{
inout[cnt]=now;
in[now]=cnt;
cnt++;
reval[now] = cc+val[now]*val[now];
for(int i=0;i<maps[now].size();i++)
{
if(maps[now][i]==pre) continue;
dfs(maps[now][i],now,reval[now]);
}
inout[cnt]=now;
out[now]=cnt;
cnt++;
}
void build(int l,int r,int now)
{
//tree[now] = 0;
if(l==r)
{
tree[now]=reval[inout[l]];
return;
}
build(l,(l+r)/2,now*2);
build((l+r)/2+1,r,now*2+1);
}
int check(int l,int r,int now,int aim)
{
if(l==r)
{
return tree[now];
}
if(tree[now]>0)
{
tree[now*2]+=tree[now];
tree[now*2+1]+=tree[now];
tree[now]=0;
}
if(aim<=(l+r)/2)
check(l,(l+r)/2,now*2,aim);
else
check((l+r)/2+1,r,now*2+1,aim);
}
void change(int l,int r,int now,int ll,int rr,unsigned long long num)
{
if(ll<=l&&r<=rr)
{
tree[now]+=num;
return ;
}
if(tree[now]>0)
{
tree[now*2]+=tree[now];
tree[now*2+1]+=tree[now];
tree[now]=0;
}
if(rr<=(l+r)/2)
change(l,(l+r)/2,now*2,ll,rr,num);
else if(ll>=(l+r)/2+1)
change((l+r)/2+1,r,now*2+1,ll,rr,num);
else
{
change(l,(l+r)/2,now*2,ll,(l+r)/2,num);
change((l+r)/2+1,r,now*2+1,(l+r)/2+1,rr,num);
}
}
signed main(){
int n,m,r,i,j,k,l;
scanf("%lld",&n);
scanf("%lld",&m);
scanf("%lld",&r);
for(i=1;i<=n;i++)
{
scanf("%lld",&j);
val[i] = (unsigned long long)(j);
}
for(i=2;i<=n;i++)
{
scanf("%lld",&j);
scanf("%lld",&k);
maps[j].push_back(k);
maps[k].push_back(j);
}
dfs(r,-1,0);
build(1,2*n,1);
unsigned long long aaa;
while(m--)
{
scanf("%lld",&j);
if(j==1)
{
scanf("%lld",&k);
scanf("%lld",&l);
aaa=val[k]+(unsigned long long)l;
aaa=aaa*aaa-val[k]*val[k];
val[k] = val[k]+(unsigned long long)l;
change(1,2*n,1,in[k],out[k],aaa);
}
else
{
scanf("%lld",&k);
l=check(1,2*n,1,out[k]);
printf("%lld\n",l);
}
}
return 0;
}
京公网安备 11010502036488号