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\n",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\n", las = n - res);
	}
}
posted @ 2020-01-05 12:09  yijan  阅读(100)  评论(0编辑  收藏  举报