Pagini recente » preONI 2008 - Runda 3 | Cod sursa (job #1055073) | Cod sursa (job #1321055) | Cod sursa (job #3217176) | Cod sursa (job #3283448)
#include <stdio.h>
#include <ctype.h>
int nextc() {
int ch;
while( isspace( ch = fgetc( stdin ) ) );
return ch;
}
#include <assert.h>
#include <vector>
using ll = long long;
struct Splay {
struct Node {
int c[2], par;
// int key;
// int siz;
// ll sum;
bool flip;
Node(): par(0), flip(false) { c[0] = c[1] = 0; }
};
std::vector<Node> t;
Splay( int n ): t(n + 1) {}
// these would have been member functions of Node in pointer implementation
void push_flip( int u ) {
if( !u ) return;
t[u].flip ^= 1;
}
void push( int u ) {
int left = t[u].c[0];
int right = t[u].c[1];
if( t[u].flip ){
std::swap( t[u].c[0], t[u].c[1] );
std::swap( left, right );
t[u].flip = false;
push_flip( left );
push_flip( right );
}
}
// u is already pushed
void pull( int u ) {} // nothing to pull in dsu
int side( int u ) {
int p = t[u].par;
if( t[p].c[0] == u ) return 0;
if( t[p].c[1] == u ) return 1;
return -1;
}
void link( int p, int u, int side ) {
push( p );
if( u ) t[u].par = p;
if( p ){
t[p].c[side] = u;
pull( p );
}
}
// totul trebuie push-uit inainte de apel
void zig( int x ) {
int y = t[x].par;
int s = side( x );
// assert( s == 0 || s == 1 );
int mij = t[x].c[s ^ 1];
int up = t[y].par, sup = side( y );
link( y, mij, s );
link( x, y, s ^ 1 );
link( up, x, sup );
}
void splay( int x ) {
// assert( x ); // should never splay null
while( side( x ) >= 0 ) {
int y = t[x].par;
if( side( y ) < 0 ){
push( y );
push( x );
zig( x );
continue;
}
int z = t[y].par;
push( z );
push( y );
push( x );
int sx = side( x );
int sy = side( y );
zig( sx == sy ? y : x );
zig( x );
}
}
};
// nice trick:
// instead of maintaining trans-chain links
// a node may have a parent but not be its child
struct LinkCut : Splay {
LinkCut( int n ): Splay(n + 1) {}
// top of chain
int leftmost( int u ) {
push( u );
while( t[u].c[0] )
push( u = t[u].c[0] );
return u;
}
// forces path decomposition to contain a chain strictly from the root to u and splays u
void expose( int uu ) {
int u = uu, prev = 0; // dreapta lui u va fi castrata si lasata asa
while( u ){
splay( u );
// castram dreapta
push( u );
t[u].c[1] = prev;
pull( u );
prev = u;
u = t[u].par;
}
splay( uu );
}
void reroot( int u ) {
expose( u );
push_flip( u );
}
int Root( int u ) {
expose( u );
return leftmost( u );
}
bool Same( int u, int v ) {
return Root( u ) == Root( v );
}
void Link( int u, int v ) {
expose( v );
reroot( u );
t[u].par = v; // trans-chain edge
pull( v );
}
// void Cut( int u, int v ) {
// }
};
int main() {
FILE *fin = fopen( "disjoint.in", "r" );
FILE *fout = fopen( "disjoint.out", "w" );
int n, q;
fscanf( fin, "%d%d", &n, &q );
LinkCut zile(n);
for( int i = 0; i < q; i++ ){
int task, a, b;
fscanf( fin, "%d%d%d", &task, &a, &b );
if( task == 1 )
zile.Link( a, b );
else
fputs( zile.Same( a, b ) ? "DA\n" : "NU\n", fout );
}
fclose( fin );
fclose( fout );
return 0;
}