zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 72 F. Forced Online Queries Problem

    题目梗概

    有一张(n)个点的图,刚开始没有边,现在又两种操作,一种是加入一条边(如果这条边存在,否则删去这条边),一种是询问(x,y)是否联通。

    (x,y)给出的形式是((x+last-1)%n+1),((y+last-1)%n+1),(last)为上一次询问的答案。

    解题思路

    对于这题的离线版本有两种写法:线段树分治,以及对操作分块。

    线段树分治的做法比较常见,下面来讲讲分块的做法。

    对于当前块之前的操作,我们可以找出哪些边在当前块需要操作,设为集合(B),当然就有不需要操作的边,设为集合(C)

    对于集合(C)我们可以提前建好边,然后对于当前块的操作:如果是修改,那么直接修改集合(B);如果是询问,就往集合(C)暴力加入集合(B)的边,然后查询。

    因为集合(C)的构建次数不超过(m/P),集合(B)的大小不超过(P),所以复杂度为(msqrt mlogm)

    那么回到这道题,分块的做法十分的显然,集合(B)的定义改成可能操作的边的集合即可。

    其实线段树分治也是可以的,因为分治的过程也是按时间顺序,我们考虑这条边可能加入的位置。

    如果这条边是第奇数次确定加入,那么就可以贡献到下次可能出现的位置,直到某个位置也确定加入(即删除)。

    #include<set>
    #include<cmath>
    #include<cstdio>
    #include<algorithm>
    #define pr pair<int,int>
    #define mk make_pair
    #define fr first
    #define sc second
    #define IT set<pr>::iterator
    using namespace std;
    const int maxn=400005;
    inline int _read(){
    	int num=0;char ch=getchar();
    	while(ch<'0'||ch>'9') ch=getchar();
    	while(ch>='0'&&ch<='9') num=num*10+ch-48,ch=getchar();
    	return num;
    }
    struct jz{
    	int x,y;
    	jz(int x=0,int y=0):x(x),y(y){}
    }S[maxn];
    set<pr> A,B,C;
    void add(set<pr> &S,pr x){if (S.find(x)==S.end()) S.insert(x);else S.erase(x);}
    int n,m,L,R,K,ans[maxn],tg[maxn],tim,top,s[maxn],f[maxn];
    pr ed[maxn][2];
    int get(int x){if (f[x]==x) return x;return get(f[x]);}
    void merge(int x,int y){
    	x=get(x);y=get(y);if (x==y) return;
    	if (s[x]<s[y]) swap(x,y);S[++top]=jz(x,y);
    	s[x]+=s[y];f[y]=x;
    }
    void Back(int t){
    	while(top!=t){
    		int x=S[top].x,y=S[top].y;
    		f[y]=y;s[x]-=s[y];top--;
    	}
    }
    void add(pr h){merge(h.fr,h.sc);} 
    void Build(){
    	for (int i=1;i<=n;i++) f[i]=i,s[i]=1;top=0;
    	for (IT i=C.begin();i!=C.end();i++) add(*i);tim=top;
    }
    int ask(pr h){return get(h.fr)==get(h.sc);}
    int main(){
    	freopen("exam.in","r",stdin);
    	freopen("exam.out","w",stdout);
    	n=_read();m=_read();K=sqrt(2*m*log(m));
    	for (int j=1;j<=m;j+=K){
    		L=j;R=min(m,L+K-1);A.clear();B.clear();C.clear();
    		for (int i=L;i<=R;i++){
    			tg[i]=_read();int x=_read(),y=_read();
    			if (x>y) swap(x,y);ed[i][0]=mk(x,y);
    			x=x%n+1;y=y%n+1;
    			if (x>y) swap(x,y);ed[i][1]=mk(x,y);
    			if (tg[i]==1) A.insert(ed[i][0]),A.insert(ed[i][1]);
    		}
    		for (int i=1;i<L;i++) if (tg[i]==1){
    			if (A.find(ed[i][ans[i]])==A.end()) add(C,ed[i][ans[i]]);else add(B,ed[i][ans[i]]);
    		}
    		Build();
    		for (int i=L;i<=R;i++)
    		if (tg[i]==1) ans[i]=ans[i-1],add(B,ed[i][ans[i]]);else{
    			Back(tim);for (IT t=B.begin();t!=B.end();t++) add(*t);
    			ans[i]=ask(ed[i][ans[i-1]]);
    		}
    	}
    	for (int i=1;i<=m;i++) if (tg[i]==2) putchar(ans[i]+'0');
    	return 0;
    }
    
  • 相关阅读:
    shellscript 02 find & xargs
    PL/SQL exception
    PL/SQL 游标
    Eclipse
    【数据存储】操作资源文件
    【AsynTask】Android异步加载一张图品
    【数据存储】利用IO流操作文件
    【数据存储】DOM操作
    【特效】手指滑动:水波纹
    【数据存储】SAX操作
  • 原文地址:https://www.cnblogs.com/CHNJZ/p/11508728.html
Copyright © 2011-2022 走看看