3730: 震波
Time Limit: 15 Sec Memory Limit: 256 MBSubmit: 635 Solved: 151
[ Submit][ Status][ Discuss]
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
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
Source
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn = 1E5 + 10;
const int INF = ~0U>>1;
int n,m,LastAns,rt,Max,O,cnt,val[maxn],siz[maxn],L[maxn],MaxD[maxn];
bool Huge[maxn];
vector <int> v[maxn],G[maxn],h[maxn],Num[maxn],Dep[maxn],A[maxn],B[maxn];
int min(const int &x,const int &y) {return x < y ? x : y;}
void Dfs1(int x,int tot,int fa)
{
int ma = 0; siz[x] = 1;
for (int i = 0; i < v[x].size(); i++)
{
int to = v[x][i];
if (to == fa || Huge[to]) continue;
Dfs1(to,tot,x); siz[x] += siz[to]; ma = max(ma,siz[to]);
}
ma = max(ma,tot - siz[x]);
if (ma < Max) Max = ma,O = x;
}
void Dfs2(int x,int fa)
{
for (int i = 0; i < v[x].size(); i++)
{
int to = v[x][i]; if (to == fa || Huge[to]) continue;
L[to] = MaxD[to] = L[x] + 1; Dfs2(to,x); MaxD[x] = max(MaxD[x],MaxD[to]);
}
}
void Dfs3(int x,int o,int y,int num,int t1,int t2,int fa)
{
siz[x] = 1; Num[x].push_back(num); Dep[x].push_back(L[x]);
for (int i = L[x]; i <= t1; i += i&-i) A[o][i] += val[x];
for (int i = L[x]; i <= t2; i += i&-i) B[y][i] += val[x];
for (int i = 0; i < v[x].size(); i++)
{
int to = v[x][i];
if (Huge[to] || to == fa) continue;
Dfs3(to,o,y,num,t1,t2,x); siz[x] += siz[to];
}
}
int Work(int x,int tot)
{
Max = INF; Dfs1(x,tot,0); int o = O,Now = 0;
Huge[o] = 1; L[o] = MaxD[o] = 0; Dfs2(o,0);
for (int i = 0; i <= MaxD[o]; i++) A[o].push_back(0);
for (int i = 0; i < v[o].size(); i++)
{
int to = v[o][i]; if (Huge[to]) continue; ++cnt;
for (int j = 0; j <= MaxD[to]; j++) B[cnt].push_back(0);
Dfs3(to,o,cnt,Now++,MaxD[o],MaxD[to],0); h[o].push_back(cnt);
}
for (int i = 0; i < v[o].size(); i++)
{
int to = v[o][i];
if (Huge[to]) continue;
int Nex = Work(to,siz[to]);
G[o].push_back(Nex);
}
return o;
}
int Query(int x,int y,int k,int now)
{
int ret = 0;
if (x == y)
{
for (int i = min(k,A[x].size() - 1); i > 0; i -= i&-i) ret += A[x][i];
return ret + val[x];
}
else
{
int Nex = h[x][Num[y][now]],st = k - Dep[y][now];
for (int i = min(st,A[x].size() - 1); i > 0; i -= i&-i) ret += A[x][i];
for (int i = min(st,B[Nex].size() - 1); i > 0; i -= i&-i) ret -= B[Nex][i];
Nex = G[x][Num[y][now]]; if (Dep[y][now] <= k) ret += val[x];
return ret + Query(Nex,y,k,now + 1);
}
}
void Modify(int x,int y,int va,int now)
{
if (x == y) {val[x] = va; return;}
int Nex = h[x][Num[y][now]],dep = Dep[y][now];
for (int j = dep; j < A[x].size(); j += j&-j) A[x][j] += (va - val[y]);
for (int j = dep; j < B[Nex].size(); j += j&-j) B[Nex][j] += (va - val[y]);
Nex = G[x][Num[y][now]];
Modify(Nex,y,va,now + 1);
}
int getint()
{
char ch = getchar(); int ret = 0;
while (ch < '0' || '9' < ch) ch = getchar();
while ('0' <= ch && ch <= '9')
ret = ret*10 + ch - '0',ch = getchar();
return ret;
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
n = getint(); m = getint();
for (int i = 1; i <= n; i++) val[i] = getint();
for (int i = 1; i < n; i++)
{
int x = getint(),y = getint();
v[x].push_back(y); v[y].push_back(x);
}
rt = Work(1,n);
for (int I = 1; I <= m; I++)
{
int typ = getint(),x = getint(),y = getint();
x ^= LastAns; y ^= LastAns; if (typ) Modify(rt,x,y,0);
else printf("%d\n",LastAns = Query(rt,x,y,0));
}
return 0;
}