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]);
	}
}



posted @ 2020-05-21 16:07  chasedeath  阅读(124)  评论(0编辑  收藏  举报