zoukankan      html  css  js  c++  java
  • 【刷题】BZOJ 3514 Codechef MARCH14 GERALD07加强版

    Description

    N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数。

    Input

    第一行四个整数N、M、K、type,代表点数、边数、询问数以及询问是否加密。

    接下来M行,代表图中的每条边。

    接下来K行,每行两个整数L、R代表一组询问。对于type=0的测试点,读入的L和R即为询问的L、R;对于type=1的测试点,每组询问的L、R应为L xor lastans和R xor lastans。

    Output

    K行每行一个整数代表该组询问的联通块个数。

    Sample Input

    3 5 4 0

    1 3

    1 2

    2 1

    3 2

    2 2

    2 3

    1 5

    5 5

    1 2

    Sample Output

    2

    1

    3

    1

    HINT

    对于100%的数据,1≤N、M、K≤200,000。

    Solution

    题目很神,还是太弱了,想不出来。LCT加主席树

    答案的求法:依次考虑每一条边,如果加入这条边 (i) 会生成环,那就删除这个环里最早加入的边 (j) ,并且记录下来 (fout[i]=j),代表 (i) 的加入弹掉了 (j) 号边

    然后发现对于一个询问 (l,r),就看在 (l)(r) 之间有多少条边 (i)(fout[i]<l),然后用 (n) 减掉这个数,就是一次询问的答案

    对于方法的解释就是,如果 (i) 边的 (fout) 小于 (l) ,那么如果只存在 (l)(r) 的边话,(i) 边必定会连接上两个联通块,答案就要-1;反之,如果它的 (fout) 大于等于 (l) ,那么这条边连的是一个联通块里的两个点,不会对答案产生贡献

    然后维护 (fout) 数组,可以用LCT维护生成树的方法

    查询 (l)(r) 之间有多少 (fout) 小于 (l) 的,可以用主席树维护

    很巧妙,要加强思维啊

    #include<bits/stdc++.h>
    #define ll long long
    #define db double
    #define ld long double
    const int MAXN=200000+10,MAXM=200000+10,inf=0x3f3f3f3f;
    int n,m,k,type,fa[MAXN],fout[MAXM],ans;
    struct edge{
    	int u,v;
    };
    edge side[MAXM];
    #define lc(x) ch[(x)][0]
    #define rc(x) ch[(x)][1]
    struct LCT{
    	int ch[MAXN+MAXM][2],fa[MAXN+MAXM],rev[MAXN+MAXM],id[MAXN+MAXM],stack[MAXN+MAXM],cnt,Mn[MAXN+MAXM],val[MAXN+MAXM];
    	inline void init()
    	{
    		memset(Mn,inf,sizeof(Mn));
    		memset(val,inf,sizeof(val));
    	}
    	inline bool nroot(int x)
    	{
    		return lc(fa[x])==x||rc(fa[x])==x;
    	}
    	inline void reverse(int x)
    	{
    		std::swap(lc(x),rc(x));
    		rev[x]^=1;
    	}
    	inline void pushup(int x)
    	{
    		Mn[x]=val[x],id[x]=x;
    		if(Mn[lc(x)]<Mn[x])Mn[x]=Mn[lc(x)],id[x]=id[lc(x)];
    		if(Mn[rc(x)]<Mn[x])Mn[x]=Mn[rc(x)],id[x]=id[rc(x)];
    	}
    	inline void pushdown(int x)
    	{
    		if(rev[x])
    		{
    			if(lc(x))reverse(lc(x));
    			if(rc(x))reverse(rc(x));
    			rev[x]=0;
    		}
    	}
    	inline void rotate(int x)
    	{
    		int f=fa[x],p=fa[f],c=(rc(f)==x);
    		if(nroot(f))ch[p][rc(p)==f]=x;
    		fa[ch[f][c]=ch[x][c^1]]=f;
    		fa[ch[x][c^1]=f]=x;
    		fa[x]=p;
    		pushup(f);
    		pushup(x);
    	}
    	inline void splay(int x)
    	{
    		cnt=0;
    		stack[++cnt]=x;
    		for(register int i=x;nroot(i);i=fa[i])stack[++cnt]=fa[i];
    		while(cnt)pushdown(stack[cnt--]);
    		for(register int y=fa[x];nroot(x);rotate(x),y=fa[x])
    			if(nroot(y))rotate((lc(y)==x)==(lc(fa[y])==y)?y:x);
    		pushup(x);
    	}
    	inline void access(int x)
    	{
    		for(register int y=0;x;x=fa[y=x])splay(x),rc(x)=y,pushup(x);
    	}
    	inline int findroot(int x)
    	{
    		access(x);splay(x);
    		while(lc(x))pushdown(x),x=lc(x);
    		splay(x);
    		return x;
    	}
    	inline void makeroot(int x)
    	{
    		access(x);splay(x);reverse(x);
    	}
    	inline void split(int x,int y)
    	{
    		makeroot(x);access(y);splay(y);
    	}
    	inline void link(int x,int y)
    	{
    		makeroot(x);fa[x]=y;
    	}
    	inline void cut(int x,int y)
    	{
    		split(x,y);fa[x]=lc(y)=0;pushup(y);
    	}
    };
    LCT T1;
    #undef lc
    #undef rc
    #define Mid ((l+r)>>1)
    #define lson l,Mid
    #define rson Mid+1,r
    struct ChairMan_Tree{
    	int sum[MAXN<<5],lc[MAXN<<5],rc[MAXN<<5],root[MAXN],cnt;
    	inline void Build(int &rt,int l,int r)
    	{
    		rt=++cnt;
    		sum[rt]=0;
    		if(l==r)return ;
    		Build(lc[rt],lson);
    		Build(rc[rt],rson);
    	}
    	inline void Insert(int &rt,int l,int r,int last,int pos)
    	{
    		rt=++cnt;
    		lc[rt]=lc[last];
    		rc[rt]=rc[last];
    		sum[rt]=sum[last]+1;
    		if(l==r)return ;
    		else
    		{
    			if(pos<=Mid)Insert(lc[rt],lson,lc[last],pos);
    			else Insert(rc[rt],rson,rc[last],pos);
    		}
    	}
    	inline int Query(int now,int last,int l,int r,int k)
    	{
    		if(r==k)return sum[now]-sum[last];
    		else
    		{
    			if(k<=Mid)return Query(lc[now],lc[last],lson,k);
    			else return sum[lc[now]]-sum[lc[last]]+Query(rc[now],rc[last],rson,k);
    		}
    	}
    };
    ChairMan_Tree T2;
    #undef Mid
    #undef lson
    #undef rson
    template<typename T> inline void read(T &x)
    {
    	T data=0,w=1;
    	char ch=0;
    	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    	if(ch=='-')w=-1,ch=getchar();
    	while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
    	x=data*w;
    }
    template<typename T> inline void write(T x,char c='')
    {
    	if(x<0)putchar('-'),x=-x;
    	if(x>9)write(x/10);
    	putchar(x%10+'0');
    	if(c!='')putchar(c);
    }
    template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
    template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
    template<typename T> inline T min(T x,T y){return x<y?x:y;}
    template<typename T> inline T max(T x,T y){return x>y?x:y;}
    inline int found(int x)
    {
    	if(fa[x]!=x)fa[x]=found(fa[x]);
    	return fa[x];
    }
    int main()
    {
    	read(n);read(m);read(k);read(type);
    	T1.init();
    	for(register int i=1;i<=n;++i)fa[i]=i;
    	for(register int i=1;i<=m;++i)
    	{
    		int u,v,sn=i+n,x,y;
    		read(u);read(v);
    		side[i].u=u;side[i].v=v;
    		if(u==v)
    		{
    			fout[i]=i;
    			continue;
    		}
    		x=found(u),y=found(v);
    		if(x!=y)
    		{
    			fa[x]=y;
    			T1.val[sn]=i;
    			T1.link(sn,u);T1.link(sn,v);
    		}
    		else
    		{
    			T1.split(u,v);
    			int so=T1.id[v];
    			fout[i]=so-n;
    			T1.cut(so,side[so-n].u);T1.cut(so,side[so-n].v);
    			T1.val[sn]=i;
    			T1.link(sn,u);T1.link(sn,v);
    		}
    	}
    	T2.Build(T2.root[0],0,m);
    	for(register int i=1;i<=m;++i)T2.Insert(T2.root[i],0,m,T2.root[i-1],fout[i]);
    	while(k--)
    	{
    		int l,r;
    		read(l);read(r);
    		if(type)l^=ans,r^=ans;
    		ans=n-T2.Query(T2.root[r],T2.root[l-1],0,m,l-1);
    		write(ans,'
    ');
    	}
    	return 0;
    }
    
  • 相关阅读:
    页码pageNo与SQL的limit进行换算
    Linux(centos)使用shell脚本停止启动jar包
    Linux执行脚本报错:-bash: ./xx.sh: /bin/bash^M: bad interpreter: No such file or directory
    Linux启动、停止宝塔
    Linux报错:ERROR>the input device is not a TTY
    mybatis基于注解的sql中空字符串判断
    题解 「CTSC2018暴力写挂」
    题解 Beautiful Pair
    【模板】常系数齐次线性递推
    斐波那契的最小公倍数 题解
  • 原文地址:https://www.cnblogs.com/hongyj/p/8724434.html
Copyright © 2011-2022 走看看