就不发题意了...
LCT模板题,和http://www.spoj.com/problems/DYNACON1/一样,但是不卡常数。
并查集做法见:http://blog.csdn.net/braketbn/article/details/50733104
数组:
#include <cstdio> #include <algorithm> using namespace std; const int maxn = 100005; int n, m, son[maxn][2], pre[maxn]; bool rev[maxn]; inline int iread() { int f = 1, x = 0; char ch = getchar(); for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1; for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0'; return f * x; } inline bool isroot(int x) { return son[pre[x]][0] != x && son[pre[x]][1] != x; } inline void pushdown(int x) { if(rev[x]) { rev[son[x][0]] ^= 1; rev[son[x][1]] ^= 1; swap(son[x][0], son[x][1]); rev[x] = 0; } } int sta[maxn]; inline void maintain(int x) { int top = 0; for(sta[++top] = x; !isroot(x); x = pre[x]) sta[++top] = pre[x]; for(; top; pushdown(sta[top--])); } inline void rotate(int x) { int y = pre[x], z = pre[y], type = son[y][1] == x; pre[son[y][type] = son[x][!type]] = y; pre[x] = z; if(!isroot(y)) son[z][son[z][1] == y] = x; pre[son[x][!type] = y] = x; } inline void splay(int x) { maintain(x); while(!isroot(x)) { int y = pre[x], z = pre[y]; if(isroot(y)) rotate(x); else if(son[z][1] == y ^ son[y][1] == x) rotate(x), rotate(x); else rotate(y), rotate(x); } } inline void access(int x) { for(int y = 0; x; x = pre[y = x]) { splay(x); son[x][1] = y; } } inline void makeroot(int x) { access(x); splay(x); rev[x] ^= 1; } inline int findroot(int x) { access(x); splay(x); for(; son[x][0]; x = son[x][0]); return x; } inline void link(int a, int b) { makeroot(a); pre[a] = b; } inline void cut(int a, int b) { makeroot(a); access(b); splay(b); son[b][0] = pre[a] = 0; } inline bool check(int a, int b) { if(findroot(a) == findroot(b)) return 1; return 0; } int main() { n = iread(); m = iread(); while(m--) { char ch = getchar(); for(; ch != 'C' && ch != 'D' && ch != 'Q'; ch = getchar()); int a = iread(), b = iread(); if(ch == 'C') link(a, b); else if(ch == 'D') cut(a, b); else printf(check(a, b) ? "Yes\n" : "No\n"); } return 0; }
指针:
#include <cstdio> #include <algorithm> using namespace std; const int maxn = 100005; int n, m; struct node { node *son[2], *pre; bool rev; } pool[maxn], *null; inline int iread() { int f = 1, x = 0; char ch = getchar(); for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1; for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0'; return f * x; } inline bool isroot(node *x) { return x->pre->son[0] != x && x->pre->son[1] != x; } inline void pushdown(node *x) { if(x->rev) { x->son[0]->rev ^= 1; x->son[1]->rev ^= 1; swap(x->son[0], x->son[1]); x->rev = 0; } } node *sta[maxn]; inline void maintain(node *x) { int top = 0; for(sta[++top] = x; !isroot(x); x = x->pre) sta[++top] = x->pre; for(; top; pushdown(sta[top--])); } inline void rotate(node *x) { node *y = x->pre, *z = y->pre; int type = y->son[1] == x; y->son[type] = x->son[!type]; x->son[!type]->pre = y; x->pre = z; if(!isroot(y)) z->son[z->son[1] == y] = x; x->son[!type] = y; y->pre = x; } inline void splay(node *x) { maintain(x); while(!isroot(x)) { node *y = x->pre, *z = y->pre; if(isroot(y)) rotate(x); else if(z->son[1] == y ^ y->son[1] == x) rotate(x), rotate(x); else rotate(y), rotate(x); } } inline void access(node *x) { for(node *y = null; x != null; x = x->pre) { splay(x); x->son[1] = y; y = x; } } inline void makeroot(node *x) { access(x); splay(x); x->rev ^= 1; } inline node* findroot(node* x) { access(x); splay(x); for(; x->son[0] != null; x = x->son[0]); return x; } inline void link(int x, int y) { node *a = pool + x, *b = pool + y; makeroot(a); a->pre = b; } inline void cut(int x, int y) { node *a = pool + x, *b = pool + y; makeroot(a); access(b); splay(b); b->son[0] = a->pre = pool; } inline bool check(int x, int y) { node *a = pool + x, *b = pool + y; if(findroot(a) == findroot(b)) return 1; return 0; } int main() { n = iread(); m = iread(); null = pool; null->son[0] = null->son[1] = null->pre = null; null->rev = 0; for(int i = 1; i <= n; i++) { node *x = pool + i; x->son[0] = x->son[1] = x->pre = null; x->rev = 0; } while(m--) { char ch = getchar(); for(; ch != 'C' && ch != 'D' && ch != 'Q'; ch = getchar()); int a = iread(), b = iread(); if(ch == 'C') link(a, b); else if(ch == 'D') cut(a, b); else printf(check(a, b) ? "Yes\n" : "No\n"); } return 0; }