bzoj 3730: 震波 动态点分治_树链剖分_线段树

Code:

#include<bits/stdc++.h>
#define setIO(s) freopen(s".in","r",stdin) 
#define maxn 3011111 
#define N 200010  
#define inf 0x7f7f7f
using namespace std;
int hd[N],nx[N],to[N],cnt; 
int n,m,val[N],vis[N]; 
void add(int u,int v)
{
    nx[++cnt]=hd[u],hd[u]=cnt,to[cnt]=v; 
}
namespace heavyedge{
    int dep[N],hson[N],fa[N],siz[N],top[N]; 
    void dfs1(int u,int ff)
    {
        dep[u]=dep[ff]+1,fa[u]=ff,siz[u]=1; 
        for(int i=hd[u];i;i=nx[i]) 
            if(to[i]!=ff) 
            {
                dfs1(to[i],u),siz[u]+=siz[to[i]];
                if(siz[to[i]]>siz[hson[u]]) hson[u]=to[i]; 
            }
    }
    void dfs2(int u,int tp)
    {
        top[u]=tp; 
        if(hson[u]) dfs2(hson[u],tp); 
        for(int i=hd[u];i;i=nx[i])
        {
            if(to[i]==fa[u]||to[i]==hson[u]) continue; 
            dfs2(to[i],to[i]); 
        }
    }
    int LCA(int u,int v)
    {
        while(top[u]!=top[v]) dep[top[u]] < dep[top[v]] ? v = fa[top[v]] : u = fa[top[u]];  
        return dep[u] < dep[v] ? u : v; 
    }
    int main()
    {
        dfs1(1,0), dfs2(1,1); 
        return 0; 
    }
};   
int Dis(int u,int v)
{  
    return heavyedge::dep[u] + heavyedge::dep[v] - (heavyedge::dep[heavyedge::LCA(u,v)] << 1); 
}   
int siz[N],f[N],root,sn,Fa[N]; 
int GetRoot(int u,int ff)
{
    siz[u] = 1,f[u] = 0; 
    for(int i = hd[u]; i ; i = nx[i]) 
    {
        if(to[i] == ff || vis[to[i]]) continue; 
        GetRoot(to[i],u);     
        siz[u] += siz[to[i]]; 
        f[u] = max(f[u],siz[to[i]]); 
    }
    
    f[u] = max(f[u],sn - siz[u]); 
    if(f[u] < f[root]) root = u; 
}
void dfs(int u)
{
    vis[u] = 1; 
    for(int i = hd[u]; i ; i = nx[i])
    {
        if(vis[to[i]]) continue; 
        root = 0, sn = siz[to[i]], GetRoot(to[i],u);  
        Fa[root] = u, dfs(root); 
    }
}
struct Segment_Tree{
    int tot; 
    struct Node
    {
        int l,r,v; 
    }t[maxn<<1]; 
    void update(int &o,int l,int r,int p,int w)
    {
        if(!o) o = ++tot; 
        t[o].v += w; 
        if(l == r) return; 
        int mid = (l + r) >> 1;  
        if(p <= mid) update(t[o].l,l,mid,p,w); 
        else update(t[o].r,mid + 1,r,p,w); 
    }
    int query(int o,int l,int r,int L,int R)
    {
        if(!o || l > r) return 0; 
        if(l >= L && r <= R) return t[o].v; 
        int ret = 0, mid = (l + r) >> 1; 
        if(L <= mid) ret += query(t[o].l,l,mid,L,R); 
        if(mid + 1 <= R) ret += query(t[o].r,mid + 1,r,L,R); 
        return ret; 
    }     
}T; 
int ans = 0,rt[N]; 
#define fax(x) (x + n)          
int Query(int x,int k)
{     
    int ret = T.query(rt[x],0,n,0,k);  
    for(int i = x; Fa[i] ; i = Fa[i]) 
    {
        int dis = Dis(x, Fa[i]); 
        if(dis > k) continue; 
        ret += T.query(rt[Fa[i]],0,n,0,k - dis); 
        ret -= T.query(rt[fax(i)],0,n,0,k - dis); 
    }
    return ret; 
}
void Update(int x,int k)
{ 
    T.update(rt[x],0,n,0,k); 
    for(int i = x; Fa[i]; i = Fa[i])
    {
        int dis = Dis(x, Fa[i]);               //正确性显然
        T.update(rt[Fa[i]],0,n,dis,k);
        T.update(rt[fax(i)],0,n,dis,k); 
    }
}
int main()
{
    // setIO("input"); 
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n; ++i) scanf("%d",&val[i]);   
    for(int i = 1,u,v;i < n; ++i)  scanf("%d%d",&u,&v), add(u,v),add(v,u); 
    heavyedge :: main();       
    f[0] = inf, sn = n,root = 0,GetRoot(1,0), dfs(root);       
    for(int i = 1;i <= n; ++i) Update(i,val[i]);       
    while(m--)
    {
        int x,y,opt; 
        scanf("%d%d%d",&opt,&x,&y); 
        x ^= ans, y ^= ans;   
        if(opt == 0)  printf("%d\n",ans = Query(x,y)); 
        if(opt == 1)  Update(x,y-val[x]),val[x]=y;        
    }

    return 0; 
}     

  

猜你喜欢

转载自www.cnblogs.com/guangheli/p/10917607.html
今日推荐