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);
}
}