zoukankan      html  css  js  c++  java
  • 【CF1217F】Forced Online Queries Problem

    题意

    题目链接

    动态图连通性,加密方式为 ((x+l-1)mod n +1)(l=[上一次询问的两点连通]))。

    点数 (n),操作数 (m) (le 2 imes 10^5)

    Solution

    容易发现这是一个假的强制在线—— (l) 的取值只有 (0)(1) 两种,所以总共的操作种数不超过 (2 imes m)

    于是我们可以考虑采用离线解决本题的思路,我们考虑线段树分治+可撤销并查集。

    与离线不同的是,我们需要动态在线段树上添加节点。

    具体而言,我们维护每条边的时间区间,每遍历到一个叶子结点上的修改,就维护对应边的时间区间,同时在线段树上进行插入。

    code

    #include<bits/stdc++.h>
    using namespace std;
    namespace io {
    	const int SIZE=(1<<21)+1;
    	char ibuf[SIZE],*iS,*iT,obuf[SIZE],*oS=obuf,*oT=oS+SIZE-1,c,qu[55];
    	#define gc()(iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),(iS==iT?EOF:*iS++)):*iS++)
    	inline int gi (){ int x;
    		for(c=gc();c<'0'||c>'9';c=gc());
    		for(x=0;c<='9'&&c>='0';c=gc()) x=(x<<1)+(x<<3)+(c&15); return x;
    	}
    } using io::gi;
    const int N=2e5+5;
    typedef pair<int,int> pr;
    struct query
    {
    	int op,x0,y0,x1,y1;
    	bool vis[2];
    	pr nxt0,nxt1;
    } q[N];
    vector<pr> st[N<<2];
    int n,m,f[N],rk[N],stk[N],tp,lst;
    map<pr,int> mp; int mid; pr pre[N<<1];
    #define lx (x<<1)
    #define rx (x<<1|1)
    int findset(int u)
    {
    	return f[u]?findset(f[u]):u;
    }
    void unionset(int u, int v)
    {
    	u=findset(u),v=findset(v);
    	if(u!=v)
    	{
    		if (rk[u]<rk[v]) swap(u,v);
    		f[v]=u,rk[u]+=rk[v];
    		stk[++tp]=v;
    	}
    }
    void update(int x, int l, int r, int sl, int sr, pr w)
    {
    	if(sl>sr) return ;
    	if(sl<=l&&r<=sr)
    	{
    		st[x].push_back(w);
    		return ;
    	}
    	int mid=l+r>>1;
    	if(sl<=mid) update(lx,l,mid,sl,sr,w);
    	if(sr>mid) update(rx,mid+1,r,sl,sr,w);
    }
    void solve(int x, int l, int r)
    {
    	int now=tp;
    	for(auto i:st[x]) unionset(i.first,i.second);
    	if(l==r)
    	{
    		int nu=q[l].x0,nv=q[l].y0,lu=q[l].x1,lv=q[l].y1,nvis=q[l].vis[0],lvis=q[l].vis[1],r=0;
    		pr nnxt=q[l].nxt0,lnxt=q[l].nxt1;
    		if(lst) swap(nu,lu),swap(nv,lv),swap(nvis,lvis),swap(nnxt,lnxt),r=1;
    		if(q[l].op==2)
    			printf("%d",lst=(findset(nu)==findset(nv)));
    		else
    		{
    			if(!nvis)
    			{
    				update(1,1,m,l+1,nnxt.first-1,make_pair(nu,nv));
    				q[nnxt.first].vis[nnxt.second]=true;
    			}
    			if(lvis)
    			{
    				update(1,1,m,l+1,lnxt.first-1,make_pair(lu,lv));
    				q[lnxt.first].vis[lnxt.second]=true;
    			}
    		}
    	}
    	else
    	{
    		int mid=l+r>>1;
    		solve(lx,l,mid),solve(rx,mid+1,r);
    	}
    	for(;tp>now;--tp) rk[f[stk[tp]]]-=rk[stk[tp]],f[stk[tp]]=0;
    }
    int main()
    {
    	n=gi(),m=gi();
    	for(int i=1;i<=n;++i) rk[i]=1;
    	for(int i=1;i<=m;++i)
    	{
    		q[i].op=gi(),q[i].x0=gi(),q[i].y0=gi();
    		if(q[i].x0>q[i].y0) swap(q[i].x0,q[i].y0);
    		q[i].x1=q[i].x0%n+1,q[i].y1=q[i].y0%n+1;
    		if(q[i].x1>q[i].y1) swap(q[i].x1,q[i].y1);
    	}
    	for(int i=m;i;--i)
    	{
    		if(q[i].op==2) continue;
    		int tid=mp[make_pair(q[i].x0,q[i].y0)];
    		if(!tid) q[i].nxt0=make_pair(m+1,0),tid=mp[make_pair(q[i].x0,q[i].y0)]=++mid;
    		else q[i].nxt0=pre[tid];
    		if(q[i].op==1) pre[tid]=make_pair(i,0);
    		tid=mp[make_pair(q[i].x1,q[i].y1)];
    		if(!tid) q[i].nxt1=make_pair(m+1,0),tid=mp[make_pair(q[i].x1,q[i].y1)]=++mid;
    		else q[i].nxt1=pre[tid];
    		pre[tid]=make_pair(i,1);
    	}
    	solve(1,1,m);
    }
    
  • 相关阅读:
    oop klass

    广义表
    Huffman树
    二叉搜索树
    二叉树的前序、中序、后序、层序遍历
    循环链表解决约瑟夫环问题
    搭建局域网SVN代码服务器
    【CheckList】精简用例,提升执行效率,减少漏测(总结篇)
    测试资源不同时,如何有针对性的设计测试用例?
  • 原文地址:https://www.cnblogs.com/farway17/p/11601932.html
Copyright © 2011-2022 走看看