Graph Games(边分块 区间边翻转)

原题: https://ac.nowcoder.com/acm/contest/883/A

题意:

给出一个边数组,每个位置为一条无向边。开始时所有边都连着。两种操作:

  1. 翻转一个区间的边(连改为断,断改为连)
  2. 问两个点的点集(与之直接相连的点)是否相同

解析:

可以对边分块,区间修改时,中间一整段的打标记,两边的暴力。

为了方便区分点,对每个点随机一个Hash值,点集为点的Hash值异或。那么就可以通过一个数来判断点集是否相同了。


用一个数组记录每个段对每个点的贡献,当打上标记后,这个贡献就不能加上了。

暴力部分的贡献用另外一个数组进行记录。那么查询一个点的边集,相当于所有没有标记的块的贡献异或上暴力的贡献。

代码:

#include
using namespace std;
#define LL long long
#define rep(i,a,b) for(int i=a;i<=b;i++)

const int maxn=2e5+5;
const int maxm=500;
int a[maxn],b[maxn];

LL Hash[maxn>>1];
bool laz[maxm]; // 标记
LL S[maxm][maxn>>1]; // 块内状态
LL O[maxn>>1]; //本身状态
int L[maxm],R[maxm];


int main(){
    rep(i,1,1e5)Hash[i]=rand();
    int t;scanf("%d",&t);
    while(t--){
        int n,m;scanf("%d%d",&n,&m);
        rep(i,1,n)O[i]=0;
        rep(i,1,m){
            scanf("%d%d",a+i,b+i);
        }
        int ct=0,B=sqrt(m);
        for(int i=1;i<=m;i+=B){
            L[++ct]=i;
            R[ct]=min(m,i+B-1);
            rep(j,1,n)S[ct][j]=0;
            rep(j,L[ct],R[ct]){
                S[ct][a[j]]^=Hash[b[j]];
                S[ct][b[j]]^=Hash[a[j]];
            }
            laz[ct]=0;
        }
        int q;scanf("%d",&q);
        while(q--){
            int op,x,y;scanf("%d%d%d",&op,&x,&y);
            if(op-1){
                int sa=O[x],sb=O[y];
                rep(i,1,ct){
                    if(!laz[i]){
                        sa^=S[i][x];
                        sb^=S[i][y];
                    }
                }
                printf("%d",(sa==sb));
            }
            else{
                int B1=(x+B-1)/B,B2=(y+B-1)/B;
                if(B1+1<B2){
                    rep(i,B1+1,B2-1){
                        laz[i]^=1;
                    }
                    rep(i,x,R[B1]){
                        O[a[i]]^=Hash[b[i]];
                        O[b[i]]^=Hash[a[i]];
                    }
                    rep(i,L[B2],y){
                        O[a[i]]^=Hash[b[i]];
                        O[b[i]]^=Hash[a[i]];
                    }
                }
                else{
                    rep(i,x,y){
                        O[a[i]]^=Hash[b[i]];
                        O[b[i]]^=Hash[a[i]];
                    }
                }
            }
        }
        puts("");
    }
}
/*
1
5 4
1 2
1 3
2 4
3 2
3
2 1 2
2 1 3
2 1 4
*/

你可能感兴趣的:(想法题,分块)