求助,树剖60分
查看原帖
求助,树剖60分
389729
BantM楼主2024/1/9 21:14
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define debug cout<<-1<<endl
const int maxn=3e4+5;
int n,m,Q;
int aa[maxn],bb[maxn],opt[maxn],ll[maxn],rr[maxn];
map<pair<int,int>,int> op; 
vector<int>q[maxn];
int ans[maxn];
int unfa[maxn];
int rest1[maxn],rest2[maxn];
//树剖,点转边 记得dfs序-1 
int siz[maxn],dep[maxn],son[maxn],top[maxn],id[maxn],fa[maxn]; 
//线段树,a初始值为1 
int a[maxn],ca[4*maxn],sum[4*maxn];

int cnt=0,tem=0;
int find(int a){
    if(unfa[a]==a){
        return a;
    }
    unfa[a]=find(unfa[a]);
    return unfa[a];
}
void unio(int a,int b){
    if(a!=b){
        unfa[a]=b;  
    }
}
void dfs1(int p,int last){
    dep[p]=dep[fa[p]]+1;
    siz[p]=1;
    for(int i=0;i<q[p].size();i++){
        int v=q[p][i];
        if(v!=fa[p]&&op[make_pair(p,v)]!=1){
            fa[v]=p;
            dfs1(v,p);
            siz[p]+=siz[v];
            if(siz[son[p]]<siz[v]){
                son[p]=v;
            }
        }
    } 
}
void dfs2(int p,int tp){
    id[p]=++tem;top[p]=tp;
    if(son[p]){
        dfs2(son[p],tp);
    }
    for(int i=0;i<q[p].size();i++){
        int v=q[p][i];
        if(v!=fa[p]&&v!=son[p]&&op[make_pair(p,v)]!=1){
            dfs2(v,v);
        }
    } 
}

inline int ls(int a){
    return 2*a; 
}
inline int rs(int a){
    return 2*a+1;
}
inline void pushup(int a){
    sum[a]=sum[ls(a)]+sum[rs(a)];
}
void build(int l,int r,int p){
    ca[p]=-1;
    if(l==r){
        sum[p]=1;
        return;
    }
    int mid=(l+r)/2;
    build(l,mid,ls(p));
    build(mid+1,r,rs(p));
    pushup(p);
    return; 
}
inline void f(int l,int r,int p,int k){
    if(k==0){
        ca[p]=0;
        sum[p]=0;
        //cout<<":"<<p<<endl;
    }
}
void pushdown(int l,int r,int p){
    int mid=(l+r)/2;
    f(l,mid,ls(p),ca[p]);
    f(mid+1,r,rs(p),ca[p]);
    ca[p]=-1;
    return;
}
void chan(int nl,int nr,int l,int r,int p){
    if(nl<=l&&r<=nr){
        f(l,r,p,0);
        return;
    }
    pushdown(l,r,p);
    int mid=(l+r)/2;
    if(mid>=nl){
        chan(nl,nr,l,mid,ls(p));    
    }
    if(mid<nr){
        chan(nl,nr,mid+1,r,rs(p));
    }
    pushup(p);
    return;
}
int query(int nl,int nr,int l,int r,int p){
    if(nl<=l&&r<=nr){
    	//cout<<" "<<sum[p]<<" "<<p<<endl;
        return sum[p];
    }
    int ret=0;
    pushdown(l,r,p);
    int mid=(l+r)/2;
    if(mid>=nl){
        ret+=query(nl,nr,l,mid,ls(p));  
    }
    if(mid<nr){
        ret+=query(nl,nr,mid+1,r,rs(p));
    }
    return ret;
}

void change(int x,int y){
    while(top[x]!=top[y]){
        if(dep[top[x]]>dep[top[y]]){
            swap(x,y);
        }
        chan(id[top[y]],id[y],1,n,1);
        //cout<<" "<<id[top[y]]<<" "<<id[y]<<endl;
        y=fa[top[y]];   
    }
    if(id[x]>id[y]){
        swap(x,y);
    }
    if(x==y){
		return;
	}
    chan(id[x]+1,id[y],1,n,1);
    //cout<<" "<<id[x]+1<<" "<<id[y]<<endl;
}
int ask(int x,int y){
    int ret=0;
    while(top[x]!=top[y]){
        if(dep[top[x]]>dep[top[y]]){
            swap(x,y);
        }
        ret+=query(id[top[y]],id[y],1,n,1);
        y=fa[top[y]];   
    }
    if(id[x]>id[y]){
        swap(x,y);
    }
    if(x!=y){
		ret+=query(id[x]+1,id[y],1,n,1);	
	}
	//cout<<query(id[x]+1,id[y],1,n,1)<<endl;
    return ret;
}

signed main(){
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++){
        unfa[i]=i;
    }
    for(int i=1;i<=m;i++){
	    scanf("%lld%lld",&aa[i],&bb[i]);
	}
	while(1){
	    Q++;
	    scanf("%lld",&opt[Q]);
	    if(opt[Q]==1){
			scanf("%lld%lld",&ll[Q],&rr[Q]);
		}
		else if(opt[Q]==0){
			scanf("%lld%lld",&ll[Q],&rr[Q]);
			op[make_pair(ll[Q],rr[Q])]=1;
			op[make_pair(rr[Q],ll[Q])]=1;
		}
		else{
			break;
		}
	}
    for(int i=1;i<=m;i++){
        if(find(aa[i])!=find(bb[i])){
        	if(op[make_pair(aa[i],bb[i])]!=1){
				q[aa[i]].push_back(bb[i]);
				q[bb[i]].push_back(aa[i]);
				unio(find(aa[i]),find(bb[i]));  	
			} 
        }
        else{
        	if(op[make_pair(aa[i],bb[i])]!=1){
				cnt++;
				rest1[cnt]=aa[i];
				rest2[cnt]=bb[i];	
			}
        }
    }
    dfs1(1,0);
    dfs2(1,1);
    build(1,n,1);
    for(int i=1;i<=cnt;i++){
        change(rest1[i],rest2[i]);//变为0    
    }
    int tem2=0;
    for(int i=Q;i>=1;i--){
        if(opt[i]==1){
        	tem2++;
            ans[tem2]=ask(ll[i],rr[i]);
            //cout<<ans[tem]<<endl;
        }
        else if(opt[i]==0){
            change(ll[i],rr[i]);
        }
    }
    for(int i=tem2;i>=1;i--){
        printf("%lld\n",ans[i]);
    }
}
/*
5 5
1 2
1 3
3 4
4 5
4 2
0 4 2
1 5 1
-1
*/
2024/1/9 21:14
加载中...