【GDOI2016模拟3.15】染色

SOL:

  把路径拆成dep[x]+dep[y]-2*dep[lca(x,y)].

  问题变成求dep[lca(x,y)],树剖即可。

  

#include<bits/stdc++.h>
#define N 500007
#define Mid (l+r>>1)
#define ls no<<1,l,Mid
#define rs no<<1|1,Mid+1,r
#define LL long long
#define eho(x) for(int i=head[x];i;i=net[i])
#define v fall[i]
using namespace std;
int fall[N],net[N],head[N],tot,col[N];
inline void add(int x,int y){
    fall[++tot]=y; net[tot]=head[x]; head[x]=tot;
}
int siz[N],son[N],p[N],lazy[N],f[N],top[N],a[N],to,in[N],n,m,op,x,now[N];
LL dep[N],t[N],xo,kkk,sum[N];
void dfs1(int x,int fa){
    siz[x]=1; dep[x]=dep[fa]+a[x];
    eho(x) if (v^fa) {
        dfs1(v,x);
        siz[x]+=siz[v];
        if (siz[son[x]]<siz[v]) son[x]=v;
    }
//    eho(x) if (v^fa) assert(siz[son[x]]>=siz[v]);
}
void dfs2(int x,int tops) {
    p[++to]=x; in[x]=to; top[x]=tops;  
    if (son[x]) dfs2(son[x],tops);
    eho(x) if ((v^f[x])&&(v^son[x])) dfs2(v,v);
}
void build(int no,int l,int r) {
    if (l==r) {t[no]=a[p[l]]; return;} 
    build(ls); build(rs);
    t[no]=t[no<<1]+t[no<<1|1];
//    if (t[no]!=sum[r]-sum[l-1]) {
//        cout<<no<<' '<<l <<' '<<r<<endl;
//        assert(0);
//    }
}
void down(int no) {
    if (!lazy[no]) return;
    lazy[no<<1]+=lazy[no],lazy[no<<1|1]+=lazy[no],
    now[no<<1]+=lazy[no]*t[no<<1],now[no<<1|1]+=lazy[no]*now[no<<1|1],
    lazy[no]=0;
}
void add(int no,int l,int r,int L,int R){
    if (L<=l&&r<=R) {lazy[no]++;now[no]+=t[no]; return;}
    down(no);
    if (L<=Mid) add(ls,L,R);
    if (R> Mid) add(rs,L,R);
    now[no]=now[no<<1]+now[no<<1|1];
}    
LL ans=0,pp;
void query(int no,int l,int r,int L,int R){
    if (L<=l&&r<=R) {ans+=now[no]; return;}
    if (l==1&&r==2) {
        pp==0;
    }
    down(no);
    if (L<=Mid) query(ls,L,R);
    if (R> Mid) query(rs,L,R);
    if (now[no<<1]+now[no<<1|1]!=now[no]) {
        cout<<no<<' '<<l<<' '<<r<<endl;
        cout<<now[no]<<' '<<now[no<<1]<<' '<<now[no<<1|1]<<endl;
        cout<<lazy[no]<<' '<<lazy[no<<1]<<' '<<lazy[no<<1|1]<<endl;
    }
    assert(now[no<<1]+now[no<<1|1]==now[no]);
//    now[no]=now[no<<1]+now[no<<1|1];
}
void change(int x){
    while (x) {
        add(1,1,n,in[top[x]],in[x]);
        x=f[top[x]];
    }
} 
LL query(int x) {
    ans=0;
    while (x) {
        query(1,1,n,in[top[x]],in[x]);
        x=f[top[x]]; 
    } return ans;
}
signed main () {
    freopen("color1.in","r",stdin);
//    freopen("11.out","w",stdout);
    scanf("%d%d",&n,&m);
    for (int i=2;i<=n;i++) scanf("%d",f+i),f[i]++;
    for (int i=2;i<=n;i++) {
        scanf("%d",a+i); add(f[i],i);
    }
    
    dfs1(1,0); dfs2(1,1);
    for (int i=1;i<=n;i++) sum[i]=sum[i-1]+a[p[i]];
    build(1,1,n);
//    for (int i=1;i<=n;i++) printf("%d ",dep[i]);
    while (m--) {
        scanf("%d%d",&op,&x),x++;
        if (op==1&&!col[x]) change(x),xo+=dep[x],kkk++,col[x]++; 
        else if (op==2) printf("%lld\n",xo+kkk*dep[x]-2*query(x));
    } return 0;
}

 

posted @ 2018-07-19 14:51  泪寒之雪  阅读(193)  评论(0编辑  收藏  举报