萬家燈火

Description

  給你一棵\(n\)個點的樹,每一個點初始的時候有一個爲\(1\)\(0\)的權值,如今要支持兩種操做:ios

\(op(1,x)\):令\(x\)點的權值反轉c++

\(op(2,x,d)\):求距離\(x\)\(\leq d\)的點中,權值爲\(1\)的點組成的連通塊個數(注意\(x\)點自己不算在內,也就是詢問\(x\)的時候要僞裝\(x\)\(0\)數組

  數據範圍:\(1\leq n,m\leq 10^5\)spa

  

Solution

  智力康復qwq碼+調試搞了差很少一萬年也是服了qwq調試

  操做看過去濃濃的動態點分氣息,而後連通塊計數直接轉成範圍內權值爲\(1\)的點的數量\(-\)知足兩個端點的權值都是\(1\)的邊數便可code

  因此每一個分治中心上咱們要維護的東西就是:權值爲\(1\)的點的數量,兩個端點權值都是\(1\)的邊的數量ip

​  實現上的話就是樹狀數組搞一搞就行了get

  而後關於修改操做:注意到一個點修改了以後,它連出去的邊都會被影響到,然而若是修改的複雜度跟點的度數掛鉤隨便一個菊花圖就涼了,因此考慮換一種方式統計string

​  咱們把邊的貢獻掛在原樹的父親那裏,而後對於每一個點維護一下原樹兒子中有多少個權值爲\(1\)的便可it

  查詢的時候注意\(d\)\(-1\),而後還有各類奇奇怪怪的邊界的細節== 而後我個蒟蒻就寫得極其醜陋了qwq

  

  mark:連通塊仍是直接點數-邊數計算比較好。。把貢獻掛在「最上面那個點」上。。很明顯有不少不優秀的地方。。

  

Code

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=1e5+10,TOP=20,BIT=N*17*2;
struct xxx{
    int y,nxt;
}a[N*2];
char s[N];
int h[N],st[N],cnt[N];
int n,m,tot,q;
namespace Bit{/*{{{*/
    int c[BIT][2],st[N][2],mx[N][2];
    int tot=0;
    //start from 0, +1
    void modify(int which,int x,int delta,int op,int tp){//tp=0: -  tp=1: +
        ++x;
        for (;x<=mx[which][op];x+=x&-x)
            c[st[which][op]+x][tp]+=delta;
    }
    int query(int which,int op,int x,int tp){
        ++x;
        int ret=0;
        x=min(x,mx[which][op]);
        for (;x;x-=x&-x) ret+=c[st[which][op]+x][tp];
        return ret;
    }
}/*}}}*/
void add(int x,int y){a[++tot].y=y; a[tot].nxt=h[x]; h[x]=tot;}
namespace OriT{/*{{{*/
    int lis[N],dfn[N];
    int dep[N],top[N],pre[N],son[N],sz[N];
    int dfn_t;
    void predfs(int fa,int x,int d){
        int u;
        dep[x]=d; ::cnt[x]=0; pre[x]=fa;
        son[x]=0; sz[x]=1;
        for (int i=h[x];i!=-1;i=a[i].nxt){
            u=a[i].y;
            if (u==fa) continue;
            predfs(x,u,d+1);
            ::cnt[x]+=st[u];
            sz[x]+=sz[u];
            if (sz[u]>sz[son[x]]) son[x]=u;
        }
    }
    void dfs1(int fa,int x){
        lis[++dfn_t]=x; dfn[x]=dfn_t;
        if (son[x]){
            top[son[x]]=top[x];
            dfs1(x,son[x]);
        }
        int u;
        for (int i=h[x];i!=-1;i=a[i].nxt){
            u=a[i].y;
            if (u==fa||u==son[x]) continue;
            top[u]=u;
            dfs1(x,u);
        }
    }
    void prework(){
        predfs(0,1,1);
        top[1]=1; dfn_t=0;
        dfs1(0,1);
    }
    int get_lca(int x,int y){
        while (top[x]!=top[y]){
            if (dep[top[x]]<dep[top[y]]) swap(x,y);
            x=pre[top[x]];
        }
        return dep[x]<dep[y]?x:y;
    }
    int get_dis(int x,int y){
        int lca=get_lca(x,y);
        return dep[x]+dep[y]-2*dep[lca];
    }
    int jump(int x,int d){
        int aim=dep[x]-d;
        if (!d) return x;
        while (dep[top[x]]>aim) x=pre[top[x]];
        return lis[dfn[x]-(dep[x]-aim)];
    }
}/*}}}*/
namespace T{/*{{{*/
    int pre[N],sz[N],mx[N];
    int df_t[N];
    int vis[N];
    int cnt0[N],cnt1[N];//0=- 1=+
    int rec[TOP+1][N][2];
    int rt,rt_mx,mxdep;
    void get_sz(int fa,int x){
        int u;
        sz[x]=1; mx[x]=0;
        for (int i=h[x];i!=-1;i=a[i].nxt){
            u=a[i].y;
            if (u==fa||vis[u]) continue;
            get_sz(x,u);
            sz[x]+=sz[u];
            mx[x]=max(mx[x],sz[u]);
        }
    }
    void get_rt(int Rt,int fa,int x){
        int u;
        mx[x]=max(mx[x],sz[Rt]-sz[x]);
        if (mx[x]<rt_mx)
            rt=x,rt_mx=mx[x];
        for (int i=h[x];i!=-1;i=a[i].nxt){
            u=a[i].y;
            if (u==fa||vis[u]) continue;
            get_rt(Rt,x,u);
        }
    }
    void dfs(int rt_t,int fa,int x,int d,int op){
        int u;  
        mxdep=max(mxdep,d);
        cnt0[d]+=::st[x]?::cnt[x]:0;
        cnt1[d]+=::st[x];
        rec[rt_t][x][op]=d;
        for (int i=h[x];i!=-1;i=a[i].nxt){
            u=a[i].y;
            if (u==fa||vis[u]) continue;
            dfs(rt_t,x,u,d+1,op);
        }
    }
    void get_lis(int x,int rt,int which_t,int op){
        mxdep=0;
        Bit::st[rt][op]=Bit::tot;
        if (op==0)
            dfs(which_t,0,rt,0,op);
        else 
            dfs(which_t,0,x,0,op);
        Bit::mx[rt][op]=mxdep+1;
        Bit::tot+=Bit::mx[rt][op];

        for (int i=0;i<=mxdep;++i){
            Bit::modify(rt,i,cnt0[i],op,0);
            Bit::modify(rt,i,cnt1[i],op,1);
            cnt0[i]=0; cnt1[i]=0;
        }
    }
    void solve(int fa,int x){
        int u,Rt;
        rt=0,rt_mx=n;
        get_sz(0,x);
        get_rt(x,0,x);
        Rt=rt;

        df_t[Rt]=df_t[fa]+1;
        pre[Rt]=fa;
        get_lis(x,Rt,df_t[Rt],0);
        get_lis(x,Rt,df_t[Rt],1);
        vis[Rt]=1;
        for (int i=h[Rt];i!=-1;i=a[i].nxt){
            u=a[i].y;
            if (vis[u]) continue;
            solve(Rt,u);
        }
    }
    int query(int x,int aim,int d,int tp){//tp=0: -  tp=1: +
        int dis=d-OriT::get_dis(x,aim),pos;
        int ret=dis>=0?Bit::query(x,0,dis,tp):0;
        if (pre[x]){
            dis=d-OriT::get_dis(pre[x],aim)-1;
            if (dis>=0){
                ret-=Bit::query(x,1,dis,tp);
            }
            ret+=query(pre[x],aim,d,tp);
        }
        return ret;
    }
    void modify(int x,int aim,int delta,int tp){//tp=0: -  tp=1:+
        if (!delta) return;
        Bit::modify(x,rec[df_t[x]][aim][0],delta,0,tp);
        if (pre[x]){
            Bit::modify(x,rec[df_t[x]][aim][1],delta,1,tp);
            modify(pre[x],aim,delta,tp);
        }
    }
}/*}}}*/
void modify(int x){
    int delta=st[x]?-1:1;
    int fa=OriT::pre[x];
    if (fa&&st[fa])
        T::modify(fa,fa,delta,0);
    if (fa) cnt[fa]+=delta;
    T::modify(x,x,cnt[x]*delta,0);
    T::modify(x,x,delta,1);
    st[x]+=delta;
}
int query(int x,int d){
    int tmp1,tmp2,fa=OriT::pre[x];
    tmp1=T::query(x,x,d-1,0);
    tmp2=T::query(x,x,d,1);
    if (st[x]){
        --tmp2;
        tmp1-=cnt[x]+st[fa];
    }
    if (OriT::dep[x]>d){
        x=OriT::jump(x,d-1);
        fa=OriT::pre[x];
        tmp1+=st[x]&st[fa];
    }
    return tmp2-tmp1;
}
void prework(){
    OriT::prework();
    T::solve(0,1);
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("a.in","r",stdin);
#endif
    int x,y,op,d;
    scanf("%d%d",&n,&m);
    memset(h,-1,sizeof(h));
    tot=0;
    for (int i=1;i<n;++i){
        scanf("%d%d",&x,&y);
        add(x,y); add(y,x);
    }
    scanf("%s",s+1);
    for (int i=1;i<=n;++i) st[i]=s[i]=='1';
    prework();
    for (int i=1;i<=m;++i){
        scanf("%d",&op);
        if (op==1){
            scanf("%d",&x);
            modify(x);
        }
        else{
            scanf("%d%d",&x,&d);
            printf("%d\n",query(x,d));
        }
    }
}
/*
6 3
1 2
1 3
1 4
2 5
3 6
111000
2 1 2
2 4 2
1 1
2 4 2
*/
相關文章
相關標籤/搜索