就,死的挺惨的,下了第一个点一直还是没有de出来,球球各位大佬帮帮忙吧,谢谢您们了orzzzzzzzzzzzzzzz
代码里注释的是我曾经出的种种奇怪的错(哽咽
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
int inpt()
{
int x = 0, f = 1;
char ch;
for(ch = getchar(); (ch < '0' || ch > '9') && ch != '-'; ch = getchar());
if(ch == '-'){
f = -1;
ch = getchar();
}
do{
x = (x << 3) + (x << 1) + ch - '0';
ch = getchar();
}while(ch >= '0' && ch <= '9');
return x * f;
}
int n, m;
int val[MAXN];
int hd[MAXN], nxt[MAXN << 1], to[MAXN << 1], w[MAXN << 1], tot = 0;
void Add(int x, int y, int z)
{
nxt[++tot] = hd[x];
hd[x] = tot;
to[tot] = y;
w[tot] = z;
}
int ST[MAXN << 2][21], cnt = 0, first_ap[MAXN];
int dpt[MAXN], dis[MAXN];
void GetST0(int x, int fa, int dist)
{
dpt[x] = dpt[fa] + 1;
ST[++cnt][0] = x;//向后走1位表示自己(相当于实际上是向后走了2^i-1位)
first_ap[x] = cnt;
dis[x] = dist;
// if(x == 70448){
// int chao = 0;
// }
for(int i = hd[x]; i; i = nxt[i]){
int y = to[i];
if(y == fa) continue;
GetST0(y, x, dist + w[i]);
ST[++cnt][0] = x;
}
}
bool cmp(int x, int y)
{
return dpt[x] < dpt[y];
}
int lg[MAXN << 2];
void GetSTOthers()
{
for(int i = 1; i <= cnt; i++){
lg[i] = 31 - __builtin_clz(i);
}
for(int j = 1; j <= lg[cnt]; j++){
for(int i = 1; i <= cnt - (1 << j); i++){
ST[i][j] = min(ST[i][j - 1], ST[i + (1 << (j - 1))][j - 1], cmp);
}
}
}
int GetDis(int x, int y)
{
if(first_ap[x] > first_ap[y]){
swap(x, y);
}
int posx = first_ap[x], posy = first_ap[y];
int len = posy - posx + 1;
int lca = min(ST[posx][lg[len]], ST[posy - (1 << lg[len]) + 1][lg[len]], cmp);
return dis[x] + dis[y] - 2 * dis[lca];
}
int rt = 0, MaxSon[MAXN];
int vis[MAXN];
int siz[MAXN], sz[MAXN];
void GetRoot(int x, int fa, int Total)
{
MaxSon[x] = 0;
siz[x] = 1;
for(int i = hd[x]; i; i = nxt[i]){
int y = to[i];
if(y == fa || vis[y]) continue;
GetRoot(y, x, Total);
siz[x] += siz[y];
MaxSon[x] = max(MaxSon[x], siz[y]);
}
MaxSon[x] = max(MaxSon[x], Total - siz[x]);
if(MaxSon[x] < MaxSon[rt]){
rt = x;
}
}
vector<int> c[2][MAXN];
int pa[MAXN];
void BuildNewTree(int x, int Total)
{
vis[x] = 1;
sz[x] = Total + 1;
c[0][x].resize(sz[x] + 1);
c[1][x].resize(sz[x] + 1);
for(int i = hd[x]; i; i = nxt[i]){
int y = to[i];
if(vis[y]) continue;
rt = 0;
int ls = siz[y];
GetRoot(y, 0, siz[y]);
pa[rt] = x;
BuildNewTree(rt, ls);
}
}
void Change(int opt, int pos, int x, int v)
{
x++;//因为是以距离为下标,所以可能存在0,故加一排除这种情况
for(; x <= sz[pos]; x += (x & (-x))) c[opt][pos][x] += v;
}
int Ask(int opt, int pos, int x)
{
x++;//因为是以距离为下标,所以可能存在0,故加一排除这种情况
int val = 0;
x = min(x, sz[pos]);/*?????*/
for(; x; x -= (x & (-x))) val += c[opt][pos][x];
return val;
}
void Update(int x, int v)
{
for(int i = x; i; i = pa[i]) Change(0, i, GetDis(x, i), v);
for(int i = x; pa[i]; i = pa[i]) Change(1, i, GetDis(x, pa[i]), v);
}
int ans = 0;
int main()
{
// freopen("P6329_1.in", "r", stdin);
// freopen("my.out", "w", stdout);
n = inpt(), m = inpt();
for(int i = 1; i <= n; i++){
val[i] = inpt();
}
for(int i = 1; i < n; i++){
int x = inpt(), y = inpt();
Add(x, y, 1);
Add(y, x, 1);
}
GetST0(1, 0, 0);
GetSTOthers();
rt = 0;
MaxSon[0] = n;
GetRoot(1, 0, n);
BuildNewTree(rt, n);
// for(int i = 1; i <= n; i++){
// printf("%d\n", pa[i]);
// }
// return 0;
for(int i = 1; i <= n; i++){
Update(i, val[i]);
}
for(int i = 1; i <= m; i++){
int opt = inpt();
if(!opt){
int x = inpt() ^ ans, k = inpt() ^ ans;
ans = 0;
ans += Ask(0, x, k);
for(int j = x; pa[j]; j = pa[j]){
int d = GetDis(x, pa[j]);
if(k < d) break;
ans += Ask(0, pa[j], k - d) - Ask(1, j, k - d);//注意后面的那个是i!!!!!!
}
printf("%d\n", ans);
}else{
int x = inpt() ^ ans, y = inpt() ^ ans;
// ans = 0;
Update(x, y - val[x]);
val[x] = y;
}
}
return 0;
}