BZOJ震波

前言

跟烁烁的游戏一模一样

代码

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int _ = 1e5+1e2;
const int INF = 2e9;
namespace zjy_io{
    inline char gc(){
        static char buf[1<<6],*p1=buf,*p2=buf;
        return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,1<<6,stdin),p1==p2)?EOF:*p1++;
    }
    template <class T>
    inline void read(T&data){
        data=0;
        register char ch=0;
        register int caa=1;
        while((ch<'0'||ch>'9')&&ch!='-')ch=gc();
        ch=='-'?caa=-1,ch=gc():caa=1;
        while(ch<='9'&&ch>='0'){
            data=(data<<3)+(data<<1)+(ch&15);
            ch=gc();
        }
        data*=caa;
    }
    inline char Getchar(){
        register char ch=0;
        while(ch<'A'||ch>'Z')ch=gc();
        return ch;
    }
}
int vlaue[_];
using namespace zjy_io;
int mem[3000000],*pin=mem;
int n,m;
struct Tree_array{
    int size,*tree;
    int lowbit(register int k){return k&(-k);}
    void init(register int kr){tree=pin,size=kr,pin+=size+3;}
    void modify(register int loc,register int zh){
        loc=min(loc,size),++loc;
        for(register int i=loc;i<=size+1;i+=lowbit(i))tree[i]+=zh;
    }
    int query(register int l){
        l>size?l=size:l=l;
        register int ret=0;
        ++l;
        for(register int i=l;i;i-=lowbit(i))ret+=tree[i];
        return ret;
    }
};
namespace d_tree{
    int root,head[_],cnt,par[_];    
    void add(register int a,register int b){par[b]=a;}
    Tree_array node1[_],node2[_];
}
struct orginal_tree{
    struct edge{
        int nt,to;
    }e[_<<1];
    int head[_],cnt,root,size[_],all,MX;
    int dfn[_],fdfn[_],vis[_],dis[_],app[_],st[_<<1][18],tot,lg[_<<1];
    int get_lca(register int u,register int v){
        u=app[u],v=app[v];
        if(u>v)swap(u,v);
        register int LEN= lg[v-u+1];
        return fdfn[min(st[u][LEN],st[v+1-(1<<LEN)][LEN])];
    }
    int getdist(register int u,register int v){return dis[u]+dis[v]-2*dis[get_lca(u,v)];}
    void add(register int a,register int b){e[++cnt].to=b,e[cnt].nt=head[a],head[a]=cnt;}
    void dfs(register int now,register int fa){
        dfn[now]=++cnt,fdfn[cnt]=now,st[++tot][0]=cnt,app[now]=tot;
        for(register int i=head[now];i;i=e[i].nt){
            if(e[i].to==fa)continue;
            dis[e[i].to]=dis[now]+1;
            dfs(e[i].to,now);
            st[++tot][0]=dfn[now];
        }
    }
    int dfsI(register int now,register int fa){
        int len_=0;
        for(register int i=head[now];i;i=e[i].nt){
            if(e[i].to==fa||vis[e[i].to])continue;
            len_=max(len_,dfsI(e[i].to,now));
        }
        return len_+1;
    }
    void getroot(register int now,register int fa){
        size[now]=1;
        register int mx=0;
        for(register int i=head[now];i;i=e[i].nt){
            if(vis[e[i].to]||e[i].to==fa)continue;
            getroot(e[i].to,now);
            size[now]+=size[e[i].to];
            mx=max(size[e[i].to],mx);
        }
        mx=max(mx,all-size[now]);
        if(MX>mx)MX=mx,root=now;
    }
    void p_divide(register int now){
        vis[now]=1;
        for(register int i=head[now];i;i=e[i].nt){
            if(vis[e[i].to])continue;
            MX=INF;all=size[e[i].to];
            getroot(e[i].to,now);
            d_tree::add(now,root);
            d_tree::node1[root].init(dfsI(root,0)-1);
            p_divide(root);
        }
    }
    void init(){
        for(register int i=1,a,b;i<n;++i)read(a),read(b),add(a,b),add(b,a);
        cnt=0;dfs(1,0);
        register int us=2*n-1;
        for(register int j=1;j<=17;++j)
            for(register int i=1;i<=us&&i+(1<<(j-1))<=us;++i)
                st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]);
        for(register int i=2;i<=us;++i)lg[i]=lg[i>>1]+1;
        MX=INF,all=n;
        getroot(1,0);d_tree::node1[root].init(dfsI(root,0)-1);
        d_tree::root=root;
        p_divide(root);
    }
}tr;
namespace d_tree{   
    void modify(register int a,register int b){
        register int dist;
        node1[a].modify(0,b);
        for(register int i=a;par[i];i=par[i]){
            dist = tr.getdist(a,par[i]);
            node1[par[i]].modify(dist,b);
            node2[i].modify(dist,b);
        }
    }
    int query(register int a,register int b){
        register int ret=0,dist;
        ret+=node1[a].query(b);
        for(register int i=a;par[i];i=par[i]){
            dist = tr.getdist(a,par[i]);
            if(b-dist<0)continue;
            ret+=node1[par[i]].query(b-dist);
            ret-=node2[i].query(b-dist);
        }
        return ret;
    }
    void init(){
        for(register int i=1;i<=n;++i) 
            node2[i].init( node1[par[i]].size );
        for(register int i=1;i<=n;++i)
            modify(i,vlaue[i]);
    }
}
int main(){
    //freopen("data.in","r",stdin);
    //freopen("1.out","w",stdout);
    read(n),read(m);
    for(register int i=1;i<=n;++i)read(vlaue[i]);
    tr.init();
    d_tree::init();
    register int a,b,lastans=0;
    while(m--){
        read(a);
        if(a==1){
            read(a),read(b);a^=lastans;b^=lastans;
            d_tree::modify(a,b-vlaue[a]);vlaue[a]=b;
        }
        else {
            read(a);read(b);a^=lastans,b^=lastans;
            printf("%d\n",lastans=d_tree::query(a,b));
        }
    }
}

猜你喜欢

转载自blog.csdn.net/JH_2002/article/details/81391005