zoukankan      html  css  js  c++  java
  • HDU 5333(LCT)

    HDU - 5333

    多维问题容易想到离线

    从左到右,每次将\(max(u,v) \leq i\)的边加入,动态地用LCT维护一颗最大的生成树

    每次插入如果产生环,将\(min(u,v)\)较大的边保留

    满足最优性之后,加边删边的时,用树状数组维护边权\(\geq j\)的总数(即联通块减少的数量),就可以直接在树状数组上查询询问的区间

    #include<cstdio>
    #include<cctype>
    #include<iostream>
    #include<vector>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    
    #define reg register
    typedef long long ll;
    #define rep(i,a,b) for(reg int i=a,i##end=b;i<=i##end;++i)
    #define drep(i,a,b) for(reg int i=a,i##end=b;i>=i##end;--i)
    
    char IO;
    int rd(){
    	int s=0,f=0;
    	while(!isdigit(IO=getchar())) if(IO=='-') f=1;
    	do s=(s<<1)+(s<<3)+(IO^'0');
    	while(isdigit(IO=getchar()));
    	return f?-s:s;
    }
    const int N=2e5+10;
    
    int n,m,q;
    struct Edge{
    	int u,v;
    	int operator < (const Edge __) const {
    		return max(u,v)<max(__.u,__.v);
    	}
    }E[N];
    struct Node{
    	int x,id;
    	Node operator + (const Node __) const{
    		Node res;
    		res.x=min(x,__.x);
    		if(res.x==x) res.id=id;
    		else res.id=__.id;
    		return res;
    	}
    }s[N],val[N];
    struct Query{
    	int l,r,id;
    	bool operator < (const Query __) const{
    		return r<__.r;
    	}
    }Q[N];
    int Ans[N];
    int eu[N],ev[N];
    int stk[N],top;
    int fa[N],son[N][2],rev[N];
    inline int dir(int x){ return son[fa[x]][1]==x; }
    inline int isroot(int x){ return !fa[x]||(son[fa[x]][0]!=x&&son[fa[x]][1]!=x); }
    void Up(int u){
    	if(!u) return;
    	s[u]=val[u];
    	if(son[u][0]) s[u]=s[u]+s[son[u][0]];
    	if(son[u][1]) s[u]=s[u]+s[son[u][1]];
    }
    void Down(int u) {
    	if(!u || !rev[u]) return;
    	int t;
    	if(son[u][0]) {
    		t=son[u][0];
    		rev[t]^=1;
    		swap(son[t][0],son[t][1]);
    	}
    	if(son[u][1]) {
    		t=son[u][1];
    		rev[t]^=1;
    		swap(son[t][0],son[t][1]);
    	}
    	rev[u]=0;
    }
    
    
    void rotate(int u) {
    	int f=fa[u],ff=fa[f];
    	int d=dir(u);
    	fa[u]=ff; if(!isroot(f)) son[ff][dir(f)]=u;
    	son[f][d]=son[u][!d]; if(son[u][!d]) fa[son[u][!d]]=f;
    	fa[f]=u,son[u][!d]=f;
    	Up(f),Up(u),Up(ff);
    }
    void Splay(int x) {
    	static int stk[N],top=0;
    	int t=x;
    	while(!isroot(t)) stk[++top]=t,t=fa[t];
    	stk[++top]=t;
    	while(top) Down(stk[top--]);
    	while(!isroot(x)) {
    		int f=fa[x];
    		if(!isroot(f)) {
    			if(dir(x)^dir(f)) rotate(x);
    			else rotate(f);
    		}
    		rotate(x);
    	}
    }
    
    void Access(int x){ for(int t=0;x;t=x,x=fa[x]) Splay(x),son[x][1]=t,Up(x); }
    
    void MakeRoot(int x) {
    	Access(x);
    	Splay(x);
    	rev[x]^=1;
    	swap(son[x][0],son[x][1]);
    }
    int GetRoot(int x) {
    	Access(x),Splay(x);
    	while(son[x][0]) Down(x),x=son[x][0];
    	Splay(x);
    	return x;
    }
    
    
    void Cut(int x,int y) {
    	MakeRoot(x),Access(y);
    	Splay(x);
    	if(son[x][1]!=y || fa[y]!=x) puts("WTF Cut?");
    	son[x][1]=fa[y]=0;
    	Up(x);
    }
    
    struct BIT{ 
    	int s[N];
    	void init(){ memset(s,0,sizeof s); }
    	void Add(int p,int x) {
    		while(p<=n) s[p]+=x,p+=p&-p;
    	}
    	int Que(int p) {
    		int res=0;
    		while(p) res+=s[p],p-=p&-p;
    		return res;
    	}
    } B;
    
    void Link(int x,int y,int w) {
    	if(GetRoot(x)==GetRoot(y)) {
    		MakeRoot(x),Access(y);
    		Splay(y);
    		Node t=s[y];
    		if(t.x>=w) return;
    		Cut(eu[t.id],t.id);
    		Cut(ev[t.id],t.id);
    		B.Add(t.x,-1);
    		stk[++top]=t.id;
    	}
    	MakeRoot(y);
    	int t=stk[top--];
    	eu[t]=x,ev[t]=y;
    	son[t][0]=son[t][1]=rev[t]=fa[t]=0,s[t]=val[t]=(Node){w,t};
    	fa[t]=x;
    	fa[y]=t;
    	B.Add(w,1);
    }
    
    int main(){
    	while(~scanf("%d%d%d",&n,&m,&q)) {
    		top=0;
    		rep(i,n+1,n*2) stk[++top]=i;
    		rep(i,1,n*2) fa[i]=son[i][0]=son[i][1]=rev[i]=0;
    		rep(i,1,n) s[i]=val[i]=(Node){(int)1e9,0};
    		rep(i,1,m) E[i].u=rd(),E[i].v=rd();
    		sort(E+1,E+m+1);
    		rep(i,1,q) Q[i].l=rd(),Q[i].r=rd(),Q[i].id=i;
    		sort(Q+1,Q+q+1);
    		int p1=1,p2=1;
    		B.init();
    		rep(i,1,n) {
    			while(p1<=m && E[p1].u<=i&&E[p1].v<=i) {
    				Link(E[p1].u,E[p1].v,min(E[p1].u,E[p1].v));
    				p1++;
    			}
    			while(p2<=q && Q[p2].r<=i) {
    				Ans[Q[p2].id]=B.Que(Q[p2].r)-B.Que(Q[p2].l-1);
    				p2++;
    			}
    		}
    		rep(i,1,q) printf("%d\n",n-Ans[i]);
    	}
    }
    
    
    
    
  • 相关阅读:
    Delphi 获取不重复随机数《LceMeaning》
    轻松一下
    MS SQL字段类型详解《转》
    Go语言优势与劣势
    go语言特点
    初始go语言
    django 短链接改成长连接
    extjs [1]
    Supervisor安装与配置
    InfluxDB命令使用
  • 原文地址:https://www.cnblogs.com/chasedeath/p/12931425.html
Copyright © 2011-2022 走看看