BZOJ3730: 震波

BZOJ3730: 震波

https://lydsy.com/JudgeOnline/problem.php?id=3730

分析:

  • 对于点分树上的每个点\(x\),维护子树所有点到\(x\)的距离和到点分树上\(fa[x]\)的距离 。
  • 查询时查询\(x\)在点分树上到根的一条链,容斥计算答案。
  • 然后因为有修改我们使用树状数组。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <vector>
#include <iostream>
using namespace std;
#define N 100050
char buf[100000],*p1,*p2;
#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int rd() {
    int x=0;
    char s=nc();
    while(s<'0') s=nc();
    while(s>='0') x=(((x<<2)+x)<<1)+s-'0',s=nc();
    return x;
}
#define db(x) cerr<<#x<<" = "<<x<<endl
int head[N],to[N<<1],nxt[N<<1],cnt,n,m,val[N];
int siz[N],fk[N],root,tot,used[N],fa[N][20],dis[N][20],dep[N];
struct Bit {
    vector<int>b;
    void make(int s) {b.resize(s+2);}
    void fix(int x,int v) {
        x++;
        int lim=b.size();
        for(;x<lim;x+=x&(-x)) b[x]+=v;
    }
    int inq(int x) {
        x++;
        int re=0;
        x=min(x,int(b.size())-1);
        for(;x;x-=x&(-x)) re+=b[x];
        return re;
    }
}f1[N],f2[N];
inline void add(int u,int v) {
    to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt;
}
void gr(int x,int y) {
    int i;
    siz[x]=1; fk[x]=0;
    for(i=head[x];i;i=nxt[i]) if(to[i]!=y&&!used[to[i]]) {
        gr(to[i],x); siz[x]+=siz[to[i]];
        fk[x]=max(fk[x],siz[to[i]]);
    }
    fk[x]=max(fk[x],tot-siz[x]);
    if(fk[root]>fk[x]) root=x;
}
int mxd;
void gd(int x,int y,int rt,int d) {
    int i;
    mxd=max(mxd,d);
    for(i=head[x];i;i=nxt[i]) if(to[i]!=y&&!used[to[i]]) {
        mxd=max(mxd,dis[to[i]][dep[to[i]]]);
        fa[to[i]][++dep[to[i]]]=rt;
        dis[to[i]][dep[to[i]]]=d;
        gd(to[i],x,rt,d+1);
    }
}
void solve(int x) {
    used[x]=1;
    int i;
    mxd=0;
    gd(x,0,x,1);
    f1[x].make(mxd); f2[x].make(mxd);
    int all=tot;
    for(i=head[x];i;i=nxt[i]) if(!used[to[i]]) {
        tot=siz[to[i]]; 
        root=0; gr(to[i],x); solve(root);
    }
}
void upd(int x,int v) {
    int i;
    f1[x].fix(0,v);
    f2[x].fix(dis[x][dep[x]],v);
    for(i=dep[x];i;i--) {
        f1[fa[x][i]].fix(dis[x][i],v);
        f2[fa[x][i]].fix(dis[x][i-1],v);
    }
}
int query(int x,int k) {
    int i,re=f1[x].inq(k);
    for(i=dep[x];i;i--) {
        if(k>=dis[x][i]) {
            re+=f1[fa[x][i]].inq(k-dis[x][i]);
            re-=f2[fa[x][i+1]].inq(k-dis[x][i]);
        }
    }
    return re;
}
int main() {
    n=rd(),m=rd();
    int i,x,y,opt;
    for(i=1;i<=n;i++) val[i]=rd();
    for(i=1;i<n;i++) {
        x=rd(), y=rd();
        add(x,y); add(y,x);
    }
    tot=n;
    fk[0]=1ll<<30;
    gr(1,0);
    solve(root);
    for(i=1;i<=n;i++) fa[i][dep[i]+1]=i;
    for(i=1;i<=n;i++) upd(i,val[i]);
    int ans=0;
    while(m--) {
        opt=rd(), x=rd(), y=rd();
        x^=ans, y^=ans;
        if(!opt) {
            ans=query(x,y);
            printf("%d\n",ans);
        }else {
            upd(x,y-val[x]), val[x]=y;
        }
    }
}

猜你喜欢

转载自www.cnblogs.com/suika/p/10164408.html
今日推荐