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

    BZOJ 3514 Codechef MARCH14 GERALD07加强版

    看题解才会的

    如果加入一条边,它对答案是否有贡献取决于它是否与当前图形成环。

    所以加入一条边时,它形成的环里面的最早加入的边cut掉,并且给它赋值位这个最早加入边的编号。在查询的时候,初始答案位 n ,一个边挤出去的边的编号如果小于 L,说明它必然不会成环,于是就对答案有-1的贡献,否则说明它加进去会形成环,对答案没有贡献。

    这个编号存在主席树里面,就可以强制在线了。

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #include<map>
    #include<ctime>
    using namespace std;
    #define MAXN 1000216
    #define swap( a , b ) ( (a)^=(b),(b)^=(a),(a)^=(b) )
    #define pii pair<int,int>
    #define fi first
    #define se second
    int n , m , q , ty;
     
    int fa[MAXN] , ch[MAXN][2] , rev[MAXN] , S[MAXN] , val[MAXN];
    #define ls(x) ch[x][0]
    #define rs(x) ch[x][1]
    #define il inline
    #define rg register
     
    il bool nr( int x ) {
        return ch[fa[x]][0] == x || ch[fa[x]][1] == x;
    }
    il void pu( int x ) {
        S[x] = ( val[S[ch[x][0]]] > val[S[ch[x][1]]] ? S[ch[x][1]] : S[ch[x][0]] );
        if( val[x] < val[S[x]] ) S[x] = x;
    }
    il void rv( int x ) {
        swap( ch[x][0] , ch[x][1] ) , rev[x] ^= 1;
    }
    il void pd( int x ) {
        if( rev[x] ) {
            if( ch[x][0] ) rv( ch[x][0] );
            if( ch[x][1] ) rv( ch[x][1] );
            rev[x] = 0;
        }
    }
    il void ro( int x ) {
        int f = fa[x] , g = fa[f] , w = ch[fa[x]][1] == x , k = ch[x][w^1];
        if( nr( f ) ) ch[g][ch[g][1]==f] = x; ch[f][w] = k , ch[x][w ^ 1] = f;
        fa[f] = x , fa[k] = f , fa[x] = g;
        pu( f );// pu( x );
    }
    il void up( int x ) {
        if( nr( x ) ) up( fa[x] );
        pd( x );
    }
    il void sp( int x ) {
        up( x );
        int f , g;
        while( nr( x ) ) {
            f = fa[x] , g = fa[f];
            if( nr( f ) ) ro( ( ( ch[f][0] == x ) ^ ( ch[g][0] == f ) ) ? x : f );
            ro( x );
        }
        pu( x );
    }
    il void ac( int x ) {
        for( int p = 0 ; x ; ( p = x , x = fa[x] ) )
            sp( x ) , ch[x][1] = p , pu( x );
    }
    il void mr( int x ) {
        ac( x );
        sp( x );
        rv( x );
    }
    il int fr( int x ) {
        ac( x ) , sp( x );
        while( ls( x ) ) pd( x ) , x = ls( x );
        sp( x );
        return x;
    }
     
    inline bool lk( int u , int v ) {
    //    if( rand() % 2 ) swap( u , v );
        mr( u );
    //  if( fr( v ) == u ) return false;
        fa[u] = v;
        return true;
    }
    il void ct( int u , int v ) {
        mr( u );
    //  if( fr(v) == u&& fa[v] == u && !ch[v][0] ) {
        ac( v ); sp( u );
            fa[v] = ch[u][1] = 0;
            pu( u );
    //  }
    }
    inline int qr( int u , int v ) {
        mr( u ); 
    //  if( fr( v ) != u ) return -1;
        ac( v );sp( v );
        return val[S[v]];
    }
    
    int T[MAXN << 4] , ls[MAXN << 4] , rs[MAXN << 4] , idx = 0;
    int roo[MAXN];
    void build( int& rt , int l , int r ) {
    	rt = ++ idx , T[rt] = 0;
    	if( l == r ) { return; }
    	int m = l + r >> 1;
    	build( ls[rt] , l , m ) , build( rs[rt] , m + 1 , r );
    }
    void mdfy( int& rt , int old , int l , int r , int p , int c ) {
    	rt = ++ idx;
    	T[rt] = T[old] + c , ls[rt] = ls[old] , rs[rt] = rs[old];
    	if( l == r ) return;
    	int m = l + r >> 1;
    	if( p <= m ) mdfy( ls[rt] , ls[old] , l , m , p , c );
    	else mdfy( rs[rt] , rs[old] , m + 1 , r , p , c );
    }
    int que( int rt , int l , int r , int p ) {
    	if( l == r && l == p ) return 0;
    	int m = l + r >> 1;
    	if( p <= m ) return que( ls[rt] , l , m , p );
    	else return T[ls[rt]] + que( rs[rt] , m + 1 , r , p );
    }
    
    int FA[MAXN];
    int find( int x ) {
    	return x == FA[x] ? x : FA[x] = find( FA[x] );
    }
    
    pii bac[MAXN];
    int cid = 0 , res = 0x3f3f3f3f;
    int id[MAXN];
    int main() {
    //	freopen("3.in","r",stdin);
    	cin >> n >> m >> q >> ty; cid = n;
    	build( roo[0] , 1 , m );
    	memset( val , 0x3f , sizeof val );
    	for( int i = 1 ; i <= n ; ++ i ) FA[i] = i;
    	for( int i = 1 , u , v ; i <= m ;++ i ) {
    		scanf("%d%d",&u,&v);
    		if( u == v ) { roo[i] = roo[i - 1]; continue; }
    		++ cid;
    		if( find( u ) != find( v ) ) {
    			bac[cid] = make_pair( u , v );
    			FA[find( u )] = find( v );
    			val[cid] = i , pu( cid );
    			lk( u , cid ) , lk( v , cid );
    		mdfy( roo[i] , roo[i - 1] , 0 , m , 0 , 1 );
    			continue;
    		}
    		mr( u ) , ac( v ) , sp( v );
    		id[i] = val[S[v]];
    		mdfy( roo[i] , roo[i - 1] , 0 , m , val[S[v]] , 1 );
    		int U = bac[S[v]].fi , V = bac[S[v]].se , ttt = S[v];
    		ct( U , ttt ) , ct( V , ttt );
    		++ cid , bac[cid] = make_pair( u , v ) , val[cid] = i , pu( cid );
    		lk( u , cid ) , lk( v , cid );
    	}
    //	for( int i = 1 ; i <= m ; ++ i ) printf("%d
    ",id[i]);
    	int l , r , las = 0;
    	while( q --> 0 ) {
    		scanf("%d%d",&l,&r);
    		if( ty ) l ^= las , r ^= las;
    //		cout << que( roo[r] , 0 , m , l ) << endl;
    		int res = que( roo[r] , 0 , m , l ) - que( roo[l - 1] , 0 , m , l );
    		printf("%d
    ", las = n - res);
    	}
    }
    
  • 相关阅读:
    C#连接MySQL
    国双面试题
    Redis入门安装配置
    vs2013密钥
    单例模式
    用R画韦恩图
    Snipaste截图
    秩和检验
    用R包中heatmap画热图
    OTU(operational taxonomic units),即操作分类单元
  • 原文地址:https://www.cnblogs.com/yijan/p/bzoj3514.html
Copyright © 2011-2022 走看看