BZOJ 3730: 震波(动态点分治)

3730: 震波

Time Limit: 15 Sec  Memory Limit: 256 MB
Submit: 3441  Solved: 611
[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

包含若干行,对于每个询问输出一行一个正整数表示答案。

#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn=2e5+10;
vector<int>G[maxn];
vector<int>bit[maxn],rbit[maxn];
int a[maxn],n,m,dist[maxn][20];
int root,now_size,son[maxn];
int vis[maxn],f[maxn][20];
int dep[maxn];
void get_root(int v,int fa,int SIZE)
{
    int ma=0;
    son[v]=1;
    for(int i=0;i<G[v].size();i++)
    {
        int to=G[v][i];
        if(to==fa||vis[to]) continue;
        get_root(to,v,SIZE);
        son[v]+=son[to];
        ma=max(ma,son[to]);
    }
    ma=max(ma,SIZE-son[v]);
    if(ma<now_size)
    {
        now_size=ma;
        root=v;
    }
}
void creat_new(int v,int fa,int father,int d)
{
    for(int i=0;i<G[v].size();i++)
    {
        int to=G[v][i];
        if(to==fa||vis[to]) continue;
        f[to][++dep[to]]=father;
        dist[to][dep[to]]=d;
        creat_new(to,v,father,d+1);
    }
}
void build(int v,int fa)
{
    vis[v]=1;
    bit[v].resize(sz+1);
    rbit[v].resize(sz+1);
    creat_new(v,fa,v,1);
    for(int i=0;i<G[v].size();i++)
    {
        int to=G[v][i];
        if(to==fa||vis[to]) continue;
        get_root(root=to,v,now_size=son[to]);
        build(root,fa,);
    }
}
void update(int x,int v)
{
    int d=dist[x][dep[x]],limt=bit[x].size()-1;
    for(int i=d;i<=limt&&i;i+=i&-i) rbit[x][i]+=v;
    for(int i=dep[x];i>0;i--)
    {
        d=dist[x][i];
        limt=bit[f[x][i]].size()-1;
        for(int j=d;j<=limt;j+=j&-j) bit[f[x][i]][j]+=v;
        d=dist[x][i-1];
        for(int j=d;j&&j<=limt;j+=j&-j) rbit[f[x][i]][j]+=v;
    }
}
int sum1(int x,int limt)
{
    int ans=a[x];
    int k=bit[x].size()-1;
    limt=min(k,limt);
    for(int i=limt;i>0;i-=i&-i) ans+=bit[x][i];
    return ans;
}
int sum2(int x,int limt)
{
    int ans=0;
    int k=rbit[x].size()-1;
    limt=min(k,limt);
    for(int i=limt;i>0;i-=i&-i) ans+=rbit[x][i];
    return ans;
}
int query(int x,int y)
{
    int ans=sum1(x,y);
    for(int i=dep[x];i>0;i--)
    {
        if(dist[x][i]<=y)
            ans+=sum1(f[x][i],y-dist[x][i])-sum2(f[x][i+1],y-dist[x][i]);
    }
    return ans;
}
int main()
{
   scanf("%d%d",&n,&m);
   for(int i=1;i<=n;i++) scanf("%d",&a[i]);
   for(int i=1;i<n;i++)
   {
       int x,y; scanf("%d%d",&x,&y);
       G[x].push_back(y);
       G[y].push_back(x);
   }
   get_root(root=1,0,n);
   sz=n;
   build(root,0,n);
   for(int i=1;i<=n;i++) f[i][dep[i]+1]=i;
   for(int i=1;i<=n;i++)
    update(i,a[i]);
   int ans=0;
   while(m--)
   {
       int op,x,y;
       scanf("%d%d%d",&op,&x,&y);
       x=x^ans;y=y^ans;
       if(op==0) printf("%d\n",ans=query(x,y));
       else update(x,y-a[x]),a[x]=y;
   }
   return 0;
}

猜你喜欢

转载自blog.csdn.net/albertluf/article/details/81567844