洛谷树

#include
#include
#include
#include
#define maxn 30100
#define lans (maxn*4 -10)
#define rans (maxn*4 -100)
#define xans (maxn*4 -20)
#define yans (maxn*4 -30)
using namespace std;
struct edges{
    int r,nxt,w;
}e[maxn<<1];
int head[maxn],esz;
int dep[maxn],fa[maxn],top[maxn],son[maxn],id[maxn],idsz,m,w[maxn];
long long ans[maxn<<2],pre[maxn<<2][10][2],suf[maxn<<2][10][2],yh[maxn<<2];
int dfs(int u,int f,int d){
    fa[u]=f;
    dep[u]=d;
    int ssz=0,mxs=0,so=0;
    for(int t=head[u];t;t=e[t].nxt)if(e[t].r!=f){
        w[e[t].r]=e[t].w;
        int a=dfs(e[t].r,u,d+1);
        if(mxsreturn ssz+1;
}
void dfs2(int u,int tp){
    id[u]=++idsz;
    top[u]=tp;
    if(son[u])dfs2(son[u],tp);
    for(int t=head[u];t;t=e[t].nxt)
        if(e[t].r!=fa[u]&&e[t].r!=son[u])
            dfs2(e[t].r,e[t].r);
}
void merge(int o,int l,int r){
    ans[o]=ans[l]+ans[r];
    for(int i=0;i<10;++i){
        int zp=(yh[l]>>i)&1;
        int zs=(yh[r]>>i)&1;
        ans[o]+=(suf[l][i][0]*pre[r][i][1]+suf[l][i][1]*pre[r][i][0])<//        printf("[%d]",(suf[l][i][0]*pre[r][i][1]+suf[l][i][1]*pre[r][i][0])<
        long long a=pre[l][i][0]+pre[r][i][zp];
        long long b=pre[l][i][1]+pre[r][i][!zp];
        long long c=suf[r][i][0]+suf[l][i][zs];
        long long d=suf[r][i][1]+suf[l][i][!zs];
        pre[o][i][0]=a;
        pre[o][i][1]=b;
        suf[o][i][0]=c;
        suf[o][i][1]=d;
    }
    yh[o]=yh[l]^yh[r];    
}
void init(int x){
    memset(pre[x],0,sizeof(pre[x]));
    memset(suf[x],0,sizeof(suf[x]));
    yh[x]=ans[x]=0;
}
void qsum(int x,int l,int r){
    if(l>r)swap(l,r);
    l+=m-1-1,r+=m+1-1;
    init(xans),init(yans);
    for(;l^r^1;l>>=1,r>>=1){
        if(~l&1)merge(xans,xans,l^1);
        if(r&1)merge(yans,r^1,yans);
    }    

    merge(xans,xans,yans);
    merge(x,xans,x);
//    printf("[%d=%d]\n",x,ans[x]);
//    for(int i=0;i<10;++i)printf("[%d,%d]\n",pre[x][i][1],pre[x][i][0]);
//    printf("\n---------------\n");
}
void modify(int l,int a){
    l+=m-1;
    ans[l]=yh[l]=a;
    for(int i=0;i<10;++i)
        pre[l][i][0]=suf[l][i][0]=pre[l][i][1]=suf[l][i][1]=0;
    for(int i=0;i<10;++i)
        pre[l][i][(a>>i)&1]++,suf[l][i][(a>>i)&1]++;
    for(l>>=1;l;l>>=1)merge(l,l<<1,l<<1|1);
}
long long calc(int l,int r){
    ans[0]=ans[l]+ans[r];
    for(int i=0;i<10;++i)
        ans[0]+=(pre[l][i][0]*pre[r][i][1]+pre[l][i][1]*pre[r][i][0])<return ans[0];
}

long long query(int u,int v){
    init(lans),init(rans),init(0);
    int tp1=top[u],tp2=top[v],l=lans,r=rans;
    while(tp1!=tp2){
        if(dep[tp1]//        printf("[%d,%d]",u,tp1);
        qsum(l,id[u],id[tp1]);
        u=fa[tp1];tp1=top[u];
    }
    if(u==v)return calc(l,r);
    if(dep[u]>dep[v])swap(u,v),swap(l,r);
    qsum(r,id[son[u]],id[v]);
    return calc(l,r);
}
void addedge(int u,int v,int w){
    e[++esz].r=v;e[esz].nxt=head[u];head[u]=esz;
    e[esz].w=w;         
}
int main(){
    int n,q;scanf("%d%d",&n,&q);
    for(int i=1;iint u,v,a;
        scanf("%d%d%d",&u,&v,&a);
        addedge(u,v,a);
        addedge(v,u,a);
    }

    dfs(1,0,1);
    dfs2(1,1);
    for(m=1;m-2<=n;m<<=1);
    for(int i=2;i<=n;++i)modify(id[i],w[i]);
    for(int i=1;i<=q;++i){
        int c,u,v,w;scanf("%d%d%d",&c,&u,&v);
        if(c==1){
            printf("%lld\n",query(u,v));
        } else {
            scanf("%d",&w);
            modify(dep[u]

你可能感兴趣的:(洛谷树)