Description
在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i]。
不幸的是,这片土地常常发生地震,并且随着时代的发展,城市的价值也往往会发生变动。
接下来你需要在线处理M次操作:
0 x k 表示发生了一次地震,震中城市为x,影响范围为k,所有与x距离不超过k的城市都将受到影响,该次地震造成的经济损失为所有受影响城市的价值和。
1 x y 表示第x个城市的价值变成了y。
为了体现程序的在线性,操作中的x、y、k都需要异或你程序上一次的输出来解密,如果之前没有输出,则默认上一次的输出为0。
Input
第一行包含两个正整数N和M。
第二行包含N个正整数,第i个数表示value[i]。
接下来N-1行,每行包含两个正整数u、v,表示u和v之间有一条无向边。
接下来M行,每行包含三个数,表示M次操作。
Output
包含若干行,对于每个询问输出一行一个正整数表示答案。
Sample Input
8 1
1 10 100 1000 10000 100000 1000000 10000000
1 2
1 3
2 4
2 5
3 6
3 7
3 8
0 3 1
Sample Output
11100101
HINT
1<=N,M<=100000
1<=u,v,x<=N
1<=value[i],y<=10000
0<=k<=N-1
第一次写冻态淀粉质,写完就不知道自己在干什么系列……
如果没有修改操作,那就是个简单的点分治;有修改,我们就把点分治的过程记录下来,对于每个分治重心,对其管辖范围内的所有点按照距离放在树状数组上维护
每次修改操作,枚举所有管辖(x)的重心,在对应树状数组中进行修改
每次询问操作,枚举所有管辖(x)的重心,在对应树状数组中进行查询
为了防止相同子树内贡献多算,我们需要在每个分治重心处维护每个子树的树状数组来减掉
树状数组动态空间,我们可以开一个全局的数组,然后剥离一段段区间下发给每个树状数组;对每个分治重心维护子树树状数组可以用map+pair记录;对于每个点用vector记录三元组((x,y,dis)),表示管辖其的重心(x),(y)是(x)的直接儿子且子树内包含该点,(dis)记录该点到(x)的距离;树状数组查询时为了防止(dis=0),可以对所有距离+1
细节多……不过自己YY出来的还是很有成就感,常数略大……
/*program from Wolfycz*/
#include<map>
#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define Fi first
#define Se second
#define MK make_pair
#define inf 0x7f7f7f7f
#define lowbit(x) ((x)&-(x))
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef pair<int,int> pii;
typedef unsigned long long ull;
inline char gc(){
static char buf[1000000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
inline int frd(){
int x=0,f=1; char ch=gc();
for (;ch<'0'||ch>'9';ch=gc()) if (ch=='-') f=-1;
for (;ch>='0'&&ch<='9';ch=gc()) x=(x<<3)+(x<<1)+ch-'0';
return x*f;
}
inline int read(){
int x=0,f=1; char ch=getchar();
for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1;
for (;ch>='0'&&ch<='9';ch=getchar()) x=(x<<3)+(x<<1)+ch-'0';
return x*f;
}
inline void print(int x){
if (x<0) putchar('-'),x=-x;
if (x>9) print(x/10);
putchar(x%10+'0');
}
const int N=1e5,M=2e6;
int pre[(N<<1)+10],now[N+10],child[(N<<1)+10];
int size[N+10],h[N+10],deep[N+10],V[N+10];
bool vis[N+10];
int root,Max,tot,top;
map<pii,int>Mp;
struct S1{
int x,Rem,dis;
S1(){x=Rem=dis=0;}
S1(int _x,int _r,int _d){x=_x,Rem=_r,dis=_d;}
void insert(int _x,int _r,int _d){x=_x,Rem=_r,dis=_d;}
};
vector<S1>vec[N+10];
int tree[M+10],remain,BIT_cnt;
struct S2{
int val,delta,len;
void init(int x,int v){delta=remain,remain+=(len=x),val=v;}
void insert(int x,int v){for (;x<=len;x+=lowbit(x)) tree[x+delta]+=v;}
int Query(int x){
x=min(x,len); int res=0;
if (x<=0) return res;
for (;x;x-=lowbit(x)) res+=tree[x+delta];
return res*val;
}
}BIT[(N<<1)+10];//Binary Indexed Tree
void join(int x,int y){pre[++tot]=now[x],now[x]=tot,child[tot]=y;}
void insert(int x,int y){join(x,y),join(y,x);}
void Get_root(int x,int fa,int sz){
int res=0; size[x]=1;
for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
if (son==fa||vis[son]) continue;
Get_root(son,x,sz);
res=max(res,size[son]);
size[x]+=size[son];
}
res=max(res,sz-size[x]);
if (res<Max) Max=res,root=x;
}
int solve(int x,int fa,int belong){
deep[x]=deep[fa]+1,h[++top]=x;
int res=deep[x];
S1 tmp(root,belong,deep[x]);
vec[x].push_back(tmp);
for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
if (son==fa||vis[son]) continue;
res=max(res,solve(son,x,belong));
}
return res;
}
void divide(int x){
static int tmp[N+10]; vis[x]=1;
int tail=0,Md=1; deep[x]=1;
tmp[++tail]=x;
S1 t(x,0,deep[x]);
vec[x].push_back(t);
for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
if (vis[son]) continue;
top=0; int dep=solve(son,x,son);
Mp.insert(map<pii,int>::value_type(MK(x,son),++BIT_cnt));
BIT[BIT_cnt].init(dep,-1);
for (int i=1;i<=top;i++) BIT[BIT_cnt].insert(deep[h[i]],V[h[i]]),tmp[++tail]=h[i];
Md=max(Md,dep);
}
BIT[x].init(Md,1);
for (int i=1;i<=tail;i++) BIT[x].insert(deep[tmp[i]],V[tmp[i]]);
for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
if (vis[son]) continue;
root=0,Max=inf;
Get_root(son,x,size[son]);
divide(root);
}
}
int main(){
int n=read(),m=read(); BIT_cnt=n;
for (int i=1;i<=n;i++) V[i]=read();
for (int i=1;i<n;i++){
int x=read(),y=read();
insert(x,y);
}
root=0,Max=inf;
Get_root(1,0,n);
divide(root);
int lastans=0;
for (int i=1;i<=m;i++){
int type=read(),x=read()^lastans,y=read()^lastans;
if (type==0){
int res=0;
for (vector<S1>::iterator it=vec[x].begin();it!=vec[x].end();it++){
res=res+BIT[(*it).x].Query(y-(*it).dis+2);
map<pii,int>::iterator tmp=Mp.find(MK((*it).x,(*it).Rem));
if (tmp!=Mp.end()) res=res+BIT[tmp->Se].Query(y-(*it).dis+2);
}
printf("%d
",lastans=res);
}
if (type==1){
for (vector<S1>::iterator it=vec[x].begin();it!=vec[x].end();it++){
map<pii,int>::iterator tmp=Mp.find(MK((*it).x,(*it).Rem));
BIT[(*it).x].insert((*it).dis,y-V[x]);
if (tmp!=Mp.end()) BIT[tmp->Se].insert((*it).dis,y-V[x]);
}
V[x]=y;
}
}
return 0;
}