zoukankan      html  css  js  c++  java
  • bzoj 3514 Codechef MARCH14 GERALD07加强版

    bzoj 3514 Codechef MARCH14 GERALD07加强版

    • 所谓的加强版就是比原题多了个强制在线.原题显然可以莫队随便乱搞一下,就过了.
    • 本题强制在线,我们只能通过预处理的手段,高效回答每次询问.
    • 考虑从前往后依次加入边.如果加入的边是树边,即加入它后图中没有环,那么它会使整张图联通块个数 (-1),否则联通块个数不变.
    • 若加入边 (i) 会成环,我们在环上删掉标号最小的那条边,记这个标号为 (f) ,那么当询问区间的 (l) 大于 (f) 时,边 (i) 就是树边,贡献为 (-1) ,否则贡献为 (0) .
    • (LCT) 来实现删边加边操作,每次查询只需要知道 ([l,r]) 这个区间内有多少 (f) 是小于 (l) 的.用主席树实现即可.
    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define mp make_pair
    #define pii pair<int,int>
    inline int read()
    {
    	int x=0;
    	bool pos=1;
    	char ch=getchar();
    	for(;!isdigit(ch);ch=getchar())
    		if(ch=='-')
    			pos=0;
    	for(;isdigit(ch);ch=getchar())
    		x=x*10+ch-'0';
    	return pos?x:-x;
    }
    const int inf=1e9;
    const int MAXN=4e5+10;
    int n,m,Q,type;
    namespace LCT{
    	int stk[MAXN],tp;
    	struct node{
    		int ch[2],fa;
    		int val,mn;
    		int rev;
    		node()
    			{
    				ch[0]=ch[1]=fa=0;
    				val=mn=inf;
    				rev=0;
    			}
    	}tree[MAXN];
    	void init(int id)
    		{
    			tree[id+m].val=tree[id+m].mn=id;
    		}
    	#define root tree[x]
    	#define lson tree[root.ch[0]]
    	#define rson tree[root.ch[1]]
    	void pushup(int x)
    		{
    			root.mn=min(root.val,min(lson.mn,rson.mn));
    		}
    	void inverse(int x)
    		{
    			swap(root.ch[0],root.ch[1]);
    			root.rev^=1;
    		}
    	void pushdown(int x)
    		{
    			if(root.rev)
    				{
    					if(root.ch[0])
    						inverse(root.ch[0]);
    					if(root.ch[1])
    						inverse(root.ch[1]);
    					root.rev=0;
    				}
    		}
    	bool isroot(int x)
    		{
    			int y=root.fa;
    			return tree[y].ch[0]!=x && tree[y].ch[1]!=x;
    		}
    	void rotate(int x)
    		{
    			int y=tree[x].fa,z=tree[y].fa;
    			int k=tree[y].ch[1]==x;
    			
    			if(!isroot(y))
    				tree[z].ch[tree[z].ch[1]==y]=x;
    			tree[x].fa=z;
    			
    			tree[y].ch[k]=tree[x].ch[k^1];
    			tree[tree[x].ch[k^1]].fa=y;
    			
    			tree[x].ch[k^1]=y;
    			tree[y].fa=x;
    			pushup(y);
    		}
    	void splay(int x)
    		{
    			tp=0;
    			stk[++tp]=x;
    			for(int pos=x;!isroot(pos);pos=tree[pos].fa)
    				stk[++tp]=tree[pos].fa;
    			while(tp)
    				pushdown(stk[tp--]);
    			while(!isroot(x))
    				{
    					int y=tree[x].fa,z=tree[y].fa;
    					if(!isroot(y))
    						(tree[y].ch[0]==x)^(tree[z].ch[0]==y)?rotate(x):rotate(y);
    					rotate(x);
    				}
    			pushup(x);
    		}
    	void Access(int x)
    		{
    			for(int y=0;x;y=x,x=tree[x].fa)
    				{
    					splay(x);
    					tree[x].ch[1]=y;
    					pushup(x);
    				}
    		}
    	void makeroot(int x)
    		{
    			Access(x);
    			splay(x);
    			inverse(x);
    		}
    	int findroot(int x)
    		{
    			Access(x);
    			splay(x);
    			while(tree[x].ch[0])
    				x=tree[x].ch[0];
    			return x;
    		}
    	void split(int x,int y)
    		{
    			makeroot(x);
    			Access(y);
    			splay(y);
    		}
    	void Link(int x,int y)
    		{
    			makeroot(x);
    			tree[x].fa=y;
    		}
    	void Cut(int x,int y)
    		{
    			split(x,y);
    			tree[y].ch[0]=0;
    			tree[x].fa=0;
    			pushup(y);
    		}
    }
    namespace SEG{
    	struct node{
    		int l,r;
    		int sum,ls,rs;
    	}Tree[MAXN*30];
    	#define Root Tree[o]
    	#define Lson Tree[root.ls]
    	#define Rson Tree[root.rs]
    	int rt[MAXN],idx;
    	void BuildTree(int &o,int l,int r)
    		{
    			o=++idx;
    			Root.sum=0,Root.ls=0,Root.rs=0;
    			Root.l=l,Root.r=r;
    			if(l==r)
    				return;
    			int mid=(l+r)>>1;
    			BuildTree(Root.ls,l,mid);
    			BuildTree(Root.rs,mid+1,r);
    		}
    	void update(int &o,int pre,int pos)
    		{
    			o=++idx;
    			Root=Tree[pre];
    			++Root.sum;
    			int l=Root.l,r=Root.r;
    			if(l==r)
    				return;
    			int mid=(l+r)>>1;
    			if(pos<=mid)
    				update(Root.ls,Tree[pre].ls,pos);
    			else
    				update(Root.rs,Tree[pre].rs,pos);
    		}
    	int query(int o,int L,int R)
    		{
    			if(L>R)	
    				return 0;
    			int l=Root.l,r=Root.r;
    			if(r<L || R<l)
    				return 0;
    			if(L<=l && r<=R)	
    				return Root.sum;
    			int mid=(l+r)>>1;
    			int res=0;
    			if(L<=mid)
    				res+=query(Root.ls,L,R);
    			if(R>mid)
    				res+=query(Root.rs,L,R);
    			return res;
    		}
    }
    int lastans=0;
    int eu[MAXN],ev[MAXN];
    int main()
    {
    //	freopen("7.in","r",stdin);
    //	freopen("ans.out","w",stdout);
    	SEG::idx=0;
    	n=read(),m=read(),Q=read(),type=read();
    	SEG::BuildTree(SEG::rt[0],0,m);
    	for(int i=1;i<=m;++i)
    		{
    		//	cerr<<"solving "<<i<<endl;
    			if(i==9434)
    				{
    					int debug=1;
    				}
    			int u=read(),v=read();
    			if(u==v)
    				{
    					SEG::update(SEG::rt[i],SEG::rt[i-1],i);
    				//	printf("total:%d
    ",SEG::query(SEG::rt[i],0,m-1));
    					continue;
    				}
    			eu[i]=u,ev[i]=v;
    			int ufa=LCT::findroot(u);
    			int vfa=LCT::findroot(v);
    			if(ufa==vfa)
    				{
    					LCT::split(u,v);
    					int id=LCT::tree[LCT::tree[v].ch[0]].mn;
    					LCT::Cut(id+m,eu[id]);
    					LCT::Cut(id+m,ev[id]);
    					LCT::Link(i+m,u);
    					LCT::Link(i+m,v);
    					SEG::update(SEG::rt[i],SEG::rt[i-1],id);
    				}
    			else
    				{
    					LCT::init(i);
    					LCT::Link(i+m,u);
    					LCT::Link(i+m,v);
    					SEG::update(SEG::rt[i],SEG::rt[i-1],0);
    				}
    		//	printf("total:%d
    ",SEG::query(SEG::rt[i],0,m-1));
    		}
    	while(Q--)
    		{
    			int L=read(),R=read();
    			if(type)
    				L^=lastans,R^=lastans;
    			int Rans=SEG::query(SEG::rt[R],0,L-1);
    			int Lans=SEG::query(SEG::rt[L-1],0,L-1);
    			lastans=n-(Rans-Lans);
    			printf("%d
    ",lastans);
    		}
    	return 0;
    }
    
  • 相关阅读:
    leetcode 576. Out of Boundary Paths 、688. Knight Probability in Chessboard
    leetcode 129. Sum Root to Leaf Numbers
    leetcode 542. 01 Matrix 、663. Walls and Gates(lintcode) 、773. Sliding Puzzle 、803. Shortest Distance from All Buildings
    leetcode 402. Remove K Digits 、321. Create Maximum Number
    leetcode 139. Word Break 、140. Word Break II
    leetcode 329. Longest Increasing Path in a Matrix
    leetcode 334. Increasing Triplet Subsequence
    leetcode 403. Frog Jump
    android中webView加载H5,JS不能调用问题的解决
    通过nginx中转获取不到IP的问题解决
  • 原文地址:https://www.cnblogs.com/jklover/p/10417237.html
Copyright © 2011-2022 走看看