HDU 5333 Undirected Graph(动态树)
题意
给定一棵 \(n\) 个节点, \(m\) 条边的无向图,每个点有点权,有 \(q\) 个询问,每次询问若删去存在一个节点权值在 \([L,R]\) 范围外的边,剩下的图构成了多少个连通块(询问间相互独立)。
\(1\leq n,q \leq 10^5\)
\(1\leq m \leq 2\times 10^5\)
思路
题目意思在简化一下,就是求连接两个点权在 \([L,R]\) 中的边和原图中的所有节点构成的连通块数。
对于两维的询问,在没有强制在线的情况下,可以考虑离线消维。我们把询问按右端点升序排列,将边按照连接两点点权最大值排列,一条一条的往图中添加,加到值为 \(p\) 的边时,我们需回答 \(R\) 小于等于 \(p\) 的询问。
这样加的边满足了 \(R\) 的要求,接下来仅需考虑 \(L\) ,我们令边权为连接两点权值的最小值,显然如果增加了一条权较大的边并形成了环,那么环中较小的边便没有意义了(因为权较大的边可以影响更多的询问)。那么只需要用 \(\text{LCT}\) 维护一个最大生成树(下有讲解)即可。
继续分析,如果我们加入了一条权为 \(p\) 的边,不难发现 \(L\) 值在 \([1,p]\) 范围内的答案都会减少 \(1\)(连通块个数少 \(1\) );反过来,如果断开了一条权为 \(p\) 的边,\(L\) 值在 \([1,p]\) 的答案都会增加 \(1\) 。那在维护最大生成树的过程中,实时记录每个 \(L\) 的答案即可,我选择用树状数组进行区间修改,单点查询。
\(\text{LCT}\) 用来维护边权,最好写的写法就是直接把边当作一个点塞进 \(\text{LCT}\) 里,这个点的点权就是边权。在此基础上,用 \(\text{LCT}\) 维护最小/大生成树,只需要在连接边 \((u,v)\) 时询问目前的路径 \((u,v)\) 的最大/小值,以及对应的边的位置,如果可以替换,就断开那条边,并连接 \((u,v)\)。
代码
#include<bits/stdc++.h>
#define FOR(i,x,y) for(int i=(x),i##END=(y);i<=i##END;++i)
#define DOR(i,x,y) for(int i=(x),i##END=(y);i>=i##END;--i)
template<typename T,typename _T>inline bool chk_min(T &x,const _T y){return y<x?x=y,1:0;}
template<typename T,typename _T>inline bool chk_max(T &x,const _T y){return x<y?x=y,1:0;}
typedef long long ll;
const int N=1e5+5,M=2e5+5;
template<const int maxn,const int maxm,typename T>struct Linked_list
{
	int head[maxn],nxt[maxm],tot;T to[maxm];
	Linked_list(){clear();}
	T &operator [](const int x){return to[x];}
	void clear(){memset(head,-1,sizeof(head)),tot=0;}
	void add(int u,T v){to[tot]=v,nxt[tot]=head[u],head[u]=tot++;}
	#define EOR(i,G,u) for(int i=G.head[u];~i;i=G.nxt[i])
};
struct FenwickTree
{
	#define lowbit(x) ((x)&-(x))
	int c[N],n;
	void init(int _n){n=_n;FOR(i,0,n)c[i]=0;}
	void update(int k,int val){for(;k<=n;k+=lowbit(k))c[k]+=val;}
	int query(int k){int res=0;for(;k>0;k^=lowbit(k))res+=c[k];return res;}
	void update(int l,int r,int val){update(l,val),update(r+1,-val);}
	#undef lowbit
};
struct Query
{
	int id,l,r;
	bool operator <(const Query &_)const{return r<_.r;}
};
struct node
{
	int x,y;
	node(int _x=0,int _y=0){x=_x,y=_y;}
	bool operator <(const node &_)const{return y<_.y;}
};
struct LinkCutTree
{
	int ch[N+M][2],fa[N+M];node pw[N+M],Mi[N+M];
	int stk[N+M],tp;
	bool rev[N+M];
	void init(){create(0,node(1e9,1e9));}
	void create(int x,node val){ch[x][0]=ch[x][1]=fa[x]=rev[x]=0;pw[x]=Mi[x]=val;}
	bool isroot(int x){return x!=ch[fa[x]][0]&&x!=ch[fa[x]][1];}
	void reved(int x)
	{
		std::swap(ch[x][0],ch[x][1]);
		rev[x]^=1;
	}
	void push_up(int x)
	{
		Mi[x]=std::min(std::min(Mi[ch[x][0]],Mi[ch[x][1]]),pw[x]);
	}
	void push_down(int x)
	{
		if(rev[x])
		{
			if(ch[x][0])reved(ch[x][0]);
			if(ch[x][1])reved(ch[x][1]);
			rev[x]=0;
		}
	}
	void rotate(int x)
	{
		int y=fa[x],z=fa[y],k=(x==ch[y][1]);
		if(!isroot(y))ch[z][y==ch[z][1]]=x; fa[x]=z;
		ch[y][k]=ch[x][!k]; if(ch[x][!k])fa[ch[x][!k]]=y;
		ch[x][!k]=y,fa[y]=x;
		push_up(y),push_up(x);
	}
	void splay(int x)
	{
		stk[tp=1]=x;
		for(int y=x;!isroot(y);y=fa[y])stk[++tp]=fa[y];
		while(tp)push_down(stk[tp]),tp--;
		while(!isroot(x))
		{
			int y=fa[x],z=fa[y];
			if(!isroot(y))(x==ch[y][1])==(y==ch[z][1])?rotate(y):rotate(x);
			rotate(x);
		}
	}
	void access(int x)
	{
		for(int y=0;x;y=x,x=fa[x])
			splay(x),ch[x][1]=y,push_up(x);
	}
	void make_root(int x)
	{
		access(x),splay(x),reved(x);
	}
	int get_root(int x)
	{
		access(x),splay(x);
		while(ch[x][0])push_down(x),x=ch[x][0];
		splay(x);
		return x;
	}
	bool link(int x,int y)
	{
		make_root(x);
		if(get_root(y)==x)return false;
		fa[x]=y;
		return true;
	}
	bool cut(int x,int y)
	{
		make_root(x);
		if(get_root(y)!=x||ch[x][1]!=y||ch[y][0])return false;
		ch[x][1]=fa[y]=0;
		push_up(x);
		return true;
	}
	bool lift(int x,int y)
	{
		make_root(x);
		return get_root(y)==x;
	}
	node query(int x,int y)
	{
		lift(x,y);
		return Mi[x];
	}
};
Linked_list<N,M,int>G;
LinkCutTree LCT;
FenwickTree FT;
Query qry[N];int otp[N];
int U[N+M],V[N+M],cur;
int n,m,q;
int main()
{
	LCT.init();
	while(~scanf("%d%d%d",&n,&m,&q))
	{
		G.clear();FT.init(n);cur=n;
		FT.update(1,n,n);
		FOR(i,1,n)LCT.create(i,node(1e9,1e9));
		FOR(i,1,m)
		{
			int u,v;
			scanf("%d%d",&u,&v);
			if(u>v)std::swap(u,v);
			G.add(v,u);
		}
		FOR(i,1,q)scanf("%d%d",&qry[i].l,&qry[i].r),qry[i].id=i;
		std::sort(qry+1,qry+q+1);
		int j=1;
		FOR(i,1,n)
		{
			EOR(k,G,i)
			{
				int l=G[k];bool flg=0;
				if(!LCT.lift(i,l))flg=1;
				else
				{
					node tmp=LCT.query(i,l);
					if(tmp.y<l)
					{
						LCT.cut(tmp.x,U[tmp.x]),LCT.cut(tmp.x,V[tmp.x]);
						FT.update(1,tmp.y,1);
						flg=1;
					}
				}
				if(flg)
				{
					cur++;
					LCT.create(cur,node(cur,l));
					U[cur]=i,V[cur]=l;
					LCT.link(cur,i),LCT.link(cur,l);
					FT.update(1,l,-1);
				}
			}
			while(j<=q&&qry[j].r<=i)
			{
				otp[qry[j].id]=FT.query(qry[j].l);
				j++;
			}
		}
		FOR(i,1,q)printf("%d\n",otp[i]);
	}
	return 0;
}
HDU 5333 Undirected Graph(动态树)的更多相关文章
- HDU 5002 Tree(动态树LCT)(2014 ACM/ICPC Asia Regional Anshan Online)
		Problem Description You are given a tree with N nodes which are numbered by integers 1..N. Each node ... 
- hdu 5398 动态树LCT
		GCD Tree Time Limit: 5000/2500 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Su ... 
- HDU 2475 BOX 动态树 Link-Cut Tree
		Box Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) [Problem De ... 
- hdu 5002 (动态树lct)
		Tree Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submi ... 
- hdu 5314 动态树
		Happy King Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Tot ... 
- HDU 4010 Query on The Trees (动态树)(Link-Cut-Tree)
		题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4010 题意; 先给你一棵树,有 \(4\) 种操作: 1.如果 \(x\) 和 \(y\) 不在同一 ... 
- HDU 4836 The Query on the Tree lca || 欧拉序列 || 动态树
		lca的做法还是非常明显的.简单粗暴, 只是不是正解.假设树是长链就会跪,直接变成O(n).. 最后跑的也挺快,出题人还是挺阳光的.. 动态树的解法也是听别人说能ac的.预计就是放在splay上剖分一 ... 
- HDU 4718 The LCIS on the Tree (动态树LCT)
		The LCIS on the Tree Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Oth ... 
- SPOJ 375. Query on a tree (动态树)
		375. Query on a tree Problem code: QTREE You are given a tree (an acyclic undirected connected graph ... 
随机推荐
- 12:Css3的概念和优势
			12:Css3的概念和优势 CSS3是css技术的升级版本,CSS3语言开发是朝着模块化发展的.以前的规范作为一个模块实在是太庞大而且比较复杂,所以,把它分解为一些小的模块,更多新的模块也被加入进来. ... 
- CSS斜切角
			问题 斜切角在Web设计和印刷中是相当受欢迎的样式.它通常是在一个或多个元素的角落切一个45°的角(也就是所谓的斜切角).特别是最近,扁平化设计的势头压过了拟真设计,也使这种效果更加流行.当斜切角只存 ... 
- CentOS从源码安装Erlang
			### 首先下载资源 wget http://erlang.org/download/otp_src_18.3.tar.gz ### 解压 .tar.gz ### 安装依赖包 yum install ... 
- leetcode-Given a binary tree, find its minimum depth
			第一题 Given a binary tree, find its minimum depth.The minimum depth is the number of nodes along the s ... 
- Nginx负载均衡后端健康检查
			参考文档:https://www.cnblogs.com/kevingrace/p/6685698.html 本次使用第三方模块nginx_upstream_check_module的,要使用这个第三 ... 
- PTA天梯地图
			本题要求你实现一个天梯赛专属在线地图,队员输入自己学校所在地和赛场地点后,该地图应该推荐两条路线:一条是最快到达路线:一条是最短距离的路线.题目保证对任意的查询请求,地图上都至少存在一条可达路线. 输 ... 
- JAVA微信支付代码(WeChatPay.java 才是调用类)
			微信官方文档:https://pay.weixin.qq.com/wiki/doc/api/index.html MD5Util.java package weixin; import java.se ... 
- #WEB安全基础 : HTTP协议 | 0x0 TCP/IP四层结构
			学完HTML/CSS了? 做了这么多网页,但是你知道它们是怎么工作的吗? 作为你的朋友,我也对这些东西感兴趣,在写博客的同时也在和你一起学. 废话少说,进入正题 网络中的通信包括两个端分别为:客户端( ... 
- Vue系列之 => 评论功能(小知识点串联)
			<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ... 
- python扩展包的升级
			检查更新:pip list --outdated 更新: pip install --upgrade xxxx 
