题目连接
关于点分树的一些地方今天终于弄明白了,这个题理解的还可以,就是有点卡常,调了好久还是跑的很慢。。。。。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<queue>
#define ll long long
#define pr make_pair
#define pb push_back
//#define lc (cnt<<1)
//#define rc (cnt<<1|1)
using namespace std;
char buffer[100001],*S,*T;
inline char Get_Char()
{
if (S==T)
{
T=(S=buffer)+fread(buffer,1,100001,stdin);
if (S==T) return EOF;
}
return *S++;
}
inline int read()
{
char c;int re=0;
for(c=Get_Char();c<'0'||c>'9';c=Get_Char());
while(c>='0'&&c<='9') re=re*10+(c-'0'),c=Get_Char();
return re;
}
const int inf=0x3f3f3f3f;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const double dnf=1e15;
const int mod=1e9+7;
const double eps=1e-8;
const int maxn=100100;
int n,m;
int head[maxn],ver[maxn<<1],nt[maxn<<1],tot=1;
int a[maxn];
void add(int x,int y)
{
ver[++tot]=y,nt[tot]=head[x],head[x]=tot;
}
int d[maxn],id[maxn],rk[maxn<<1],dd[maxn<<1];
int f[maxn<<1][20],_log[maxn<<1];
int tcnt=0;
void dfs(int x,int fa)
{
id[x]=++tcnt;rk[tcnt]=x;dd[tcnt]=d[x];
for(int i=head[x];i;i=nt[i])
{
int y=ver[i];
if(y==fa) continue;
d[y]=d[x]+1;
dfs(y,x);
rk[++tcnt]=x,dd[tcnt]=d[x];
}
}
void ST(void)
{
_log[0]=-1;
for(int i=1;i<=tcnt;i++)
{
f[i][0]=i;
_log[i]=(i&(i-1))==0?_log[i-1]+1:_log[i-1];
}
int t=_log[tcnt]+1;
for(int j=1;j<=t;j++)
{
for(int i=1;i<=tcnt-(1<<j)+1;i++)
f[i][j]=dd[f[i][j-1]]<dd[f[i+(1<<(j-1))][j-1]]?f[i][j-1]:f[i+(1<<(j-1))][j-1];
}
}
int lca(int x,int y)
{
if(id[x]>id[y]) swap(x,y);
x=id[x],y=id[y];
int k=_log[y-x+1];
return dd[f[x][k]]<dd[f[y-(1<<k)+1][k]]?rk[f[x][k]]:rk[f[y-(1<<k)+1][k]];
}
int dis(int x,int y)
{
return d[x]+d[y]-2*d[lca(x,y)];
}
int maxpart[maxn],si[maxn],fa[maxn],sit[maxn];
bool ha[maxn];
int root,maxsi;
void dfs_size(int x,int fa)
{
si[x]=1,maxpart[x]=0;
for(int i=head[x];i;i=nt[i])
{
int y=ver[i];
if(y==fa||ha[y]) continue;
dfs_size(y,x);
si[x]+=si[y];
maxpart[x]=max(maxpart[x],si[y]);
}
}
void dfs_root(int nowroot,int x,int fa)
{
maxpart[x]=max(maxpart[x],si[nowroot]-si[x]);
if(maxsi>maxpart[x])
{
maxsi=maxpart[x];
root=x;
}
for(int i=head[x];i;i=nt[i])
{
int y=ver[i];
if(y==fa||ha[y]) continue;
dfs_root(nowroot,y,x);
}
}
void dfs_for_tree(int x,int f)
{
maxsi=inf;
dfs_size(x,0);
dfs_root(x,x,0);
int rt=root;
sit[rt]=si[x];
ha[rt]=true;
fa[rt]=f;
for(int i=head[rt];i;i=nt[i])
{
int y=ver[i];
if(ha[y]) continue;
dfs_for_tree(y,rt);
}
}
int cnt=0;
int rt1[maxn],rt2[maxn];
struct node
{
int lc,rc;
int sum;
}t[maxn<<7];
int newnode(void)
{
cnt++;
t[cnt].lc=t[cnt].rc=t[cnt].sum=0;
return cnt;
}
void change(int &p,int l,int r,int pos,int val)
{
if(!p) p=newnode();
t[p].sum+=val;
if(l==r) return ;
int mid=(l+r)>>1;
if(pos<=mid) change(t[p].lc,l,mid,pos,val);
else change(t[p].rc,mid+1,r,pos,val);
}
int ask(int p,int l,int r,int askl,int askr)
{
if(!p||askl>askr) return 0;
if(askl<=l&&r<=askr) return t[p].sum;
int ans=0;
int mid=(l+r)>>1;
if(askl<=mid) ans+=ask(t[p].lc,l,mid,askl,askr);
if(askr>=mid+1) ans+=ask(t[p].rc,mid+1,r,askl,askr);
return ans;
}
void change(int x,int val)
{
int now=x;
while(now)
{
change(rt1[now],0,sit[now],dis(now,x),val);
if(fa[now]) change(rt2[now],0,sit[now],dis(fa[now],x),val);
now=fa[now];
}
}
int ask(int x,int k)
{
int ans=0,now=x,last=0;
while(now)
{
int d=dis(now,x);
ans+=ask(rt1[now],0,sit[now],0,k-d);
ans-=ask(rt2[last],0,sit[last],0,k-d);
last=now;
now=fa[now];
}
return ans;
}
void init(void)
{
d[0]=-1;
dfs(1,0);
ST();
dfs_for_tree(1,0);
for(int i=1;i<=n;i++)
change(i,a[i]);
}
int main(void)
{
n=read(),m=read();
for(int i=1;i<=n;i++)
a[i]=read();
int x,y;
for(int i=1;i<n;i++)
{
x=read(),y=read();
add(x,y);
add(y,x);
}
init();
int last=0,op;
for(int i=1;i<=m;i++)
{
op=read(),x=read(),y=read();
x^=last,y^=last;
if(op==0)
printf("%d\n",last=ask(x,y));
else change(x,y-a[x]),a[x]=y;
}
return 0;
}