zoukankan      html  css  js  c++  java
  • [CF901C] Bipartite Segments

    题目大意

    给你一个有(n)个点的无向图,没有偶环。我们把节点标记为(1..n)

    你需要回答(q)个询问,每一个询问由一个区间[L,R](1<=L<=R<=n)组成,你需要计算出有多少个点对[x,y](L<=x<=y<=R),满足由[x,y]之间的所有点组成的子图是一个二分图。

    输入数据第一行两个整数 (n,m (1le nle 3 imes 10^5,1le mle 3 imes10^5))代表点数和边数 接下来的(m)行,每行两个整数,表示一条无向边,保证无自环,保证无重边

    一个整数 (q(1le qle3 imes 10^5)),表示询问个数

    接下来q行,每行一个询问[L,R]

    对于每个询问,输出一个整数,表示满足条件的点对[x,y]的个数

    解析

    首先想到的一定是”没有偶环“这一特殊的性质。仔细思考一下,没有偶环,也就等价于没有环套环的情况,因为如果有两个环套在一起,如果两个简单环都是奇环,那么一定会产生一个偶环(具体证明可以自行解决)。那么,原图就是一个仙人掌,并且所有环都是奇环。

    接下来考虑询问。二分图的条件是没有奇环,那么满足要求的区间就不能包括任何一个环。因此,首先用Tarjan求边双连通分量,把所有环找出来,记第(i)个环中最小的点为(L[i]),最大的点为(R[i]),那么对于一个区间([1,L[i]])中的点,以它为左端点的区间一定不能覆盖(R[i])及其以后的点。所以,我们可对每个点(i)求出它最远能够覆盖到的点(nxt[i])(线段树区间修改最小值),对于一个询问区间([l,r]),二分找到满足(nxt[i]<=r)的最右边的点,该点左边的用(nxt)统计答案((sum nxt[i]-i)),右边的所有子区间都满足条件,相加即为询问的答案。

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define int long long
    #define N 300002
    using namespace std;
    const int S=600001;
    const int inf=1<<30;
    struct SegmentTree{
    	int dat,add;
    }t[N*4];
    int head[N],ver[N*2],nxt[N*2],l;
    int n,m,q,i,tim,dfn[N],low[N],top,s[N],cnt,scc[N],L[N],R[N],a[N],sum[N];
    bool cut[N*2];
    int read()
    {
    	char c=getchar();
    	int w=0;
    	while(c<'0'||c>'9') c=getchar();
    	while(c<='9'&&c>='0'){
    		w=w*10+c-'0';
    		c=getchar();
    	}
    	return w;
    }
    void insert(int x,int y)
    {
    	ver[l]=y;
    	nxt[l]=head[x];
    	head[x]=l;
    	l++;
    }
    void Tarjan(int x,int pre)
    {
    	dfn[x]=low[x]=++tim;
    	for(int i=head[x];i!=-1;i=nxt[i]){
    		int y=ver[i];
    		if(!dfn[y]){
    			Tarjan(y,i);
    			low[x]=min(low[x],low[y]);
    			if(low[y]>dfn[x]) cut[i]=cut[i^1]=1;
    		}
    		else if(i!=(pre^1)) low[x]=min(low[x],dfn[y]);
    	}
    }
    void dfs(int x)
    {
    	scc[x]=cnt;
    	L[cnt]=min(L[cnt],x);
    	R[cnt]=max(R[cnt],x);
    	for(int i=head[x];i!=-1;i=nxt[i]){
    		if(cut[i]) continue;
    		int y=ver[i];
    		if(!scc[y]) dfs(y);
    	}
    }
    void update(int p)
    {
    	t[p].dat=min(t[p*2].dat,t[p*2+1].dat);
    }
    void spread(int p)
    {
    	if(t[p].add!=inf){
    		t[p*2].add=min(t[p*2].add,t[p].add);
    		t[p*2+1].add=min(t[p*2+1].add,t[p].add);
    		t[p*2].dat=min(t[p*2].dat,t[p].add);
    		t[p*2+1].dat=min(t[p*2+1].dat,t[p].add);
    		t[p].add=inf;
    	}
    }
    void build(int p,int l,int r)
    {
    	t[p].add=t[p].dat=inf;
    	if(l==r) return;
    	int mid=(l+r)/2;
    	build(p*2,l,mid);
    	build(p*2+1,mid+1,r);
    }
    void change(int p,int l,int r,int ql,int qr,int x)
    {
    	if(ql<=l&&r<=qr){
    		t[p].dat=min(t[p].dat,x);
    		t[p].add=min(t[p].add,x);
    		return;
    	}
    	int mid=(l+r)/2;
    	spread(p);
    	if(ql<=mid) change(p*2,l,mid,ql,qr,x);
    	if(qr>mid) change(p*2+1,mid+1,r,ql,qr,x);
    	update(p);
    }
    int ask(int p,int l,int r,int x)
    {
    	if(l==r) return t[p].dat;
    	int mid=(l+r)/2;
    	spread(p);
    	if(x<=mid) return ask(p*2,l,mid,x);
    	return ask(p*2+1,mid+1,r,x);
    }
    signed main()
    {
    	memset(head,-1,sizeof(head));
    	memset(L,0x3f,sizeof(L));
    	n=read();m=read();
    	for(i=1;i<=m;i++){
    		int u=read(),v=read();
    		insert(u,v);
    		insert(v,u);
    	}
    	for(i=1;i<=n;i++){
    		if(!dfn[i]) Tarjan(i,S);
    	}
    	for(i=1;i<=n;i++){
    		if(!scc[i]) cnt++,dfs(i);
    	}
    	build(1,1,n);
    	for(i=1;i<=cnt;i++){
    		if(R[i]!=L[i]) change(1,1,n,1,L[i],R[i]);
    	}
    	for(i=1;i<=n;i++){
    		a[i]=ask(1,1,n,i);
    		sum[i]=sum[i-1]+a[i]-i;
    	}
    	q=read();
    	for(i=1;i<=q;i++){
    		int x=read(),y=read();
    		int p=upper_bound(a+x,a+y+1,y)-a-1;
    		int num1=sum[p]-sum[x-1],num2=y-p;
    		printf("%lld
    ",num1+num2*(num2+1)/2);
    	}
    	return 0;
    }
    
  • 相关阅读:
    Unity3D ShaderLab 立方体图的反射遮罩
    Unity3D ShaderLab 简单的立方体图反射
    Unity3D ShaderLab 各向异性高光
    Unity3D ShaderLab 使用贴图对模型的高光进行遮罩
    Unity3D ShaderLab 使用BlinnPhong高光类型
    Unity3D ShaderLab 创建自定义高光类型
    Unity3D ShaderLab 基础的高光实现
    Unity3D ShaderLab法线贴图
    Unity3D ShaderLab压缩混合纹理贴图
    Java几种建立实例的方法
  • 原文地址:https://www.cnblogs.com/LSlzf/p/12196272.html
Copyright © 2011-2022 走看看