SPOJ QTREE3 Query on a tree again! ——Link-Cut Tree
【题目分析】
QTREE2,一看是倍增算法,太懒了,不写了。( ̄_, ̄ )
QTREE3,树链剖分可以做,发现链上的问题LCT也很好做。
要是子树问题貌似可以DFS序。
然后就成LCT模板题了。
考前背板模式开启了。
【代码】
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define maxn 100005 struct LCT{ int ch[maxn][2],fa[maxn],sta[maxn],top,rev[maxn],mx[maxn],col[maxn]; bool isroot(int x) {return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;} void update(int x) { if (~mx[ch[x][0]]) mx[x]=mx[ch[x][0]]; else if (col[x]) mx[x]=x; else if (~mx[ch[x][1]]) mx[x]=mx[ch[x][1]]; else mx[x]=-1; } void pushdown(int x) { if (rev[x]) { rev[x]^=1; rev[ch[x][0]]^=1; rev[ch[x][1]]^=1; swap(ch[x][0],ch[x][1]); } } void rot(int x) { int y=fa[x],z=fa[y],l,r; if (ch[y][0]==x) l=0; else l=1; r=l^1; if (!isroot(y)) { if (ch[z][0]==y) ch[z][0]=x; else ch[z][1]=x; } fa[x]=z; fa[y]=x; fa[ch[x][r]]=y; ch[y][l]=ch[x][r]; ch[x][r]=y; update(y);update(x); } void splay(int x) { top=0;sta[++top]=x; for (int i=x;!isroot(i);i=fa[i]) sta[++top]=fa[i]; while (top) pushdown(sta[top--]); while (!isroot(x)) { int y=fa[x],z=fa[y]; if (!isroot(y)) { if (ch[z][0]==y^ch[y][0]==z) rot(y); else rot(x); } rot(x); } } void access(int x) {for(int t=0;x;t=x,x=fa[x])splay(x),ch[x][1]=t,update(x);} void makeroot(int x) {access(x);splay(x);rev[x]^=1;} int find(int x) {access(x);splay(x);while(ch[x][0])x=ch[x][0];return x;} void link(int x,int y) {makeroot(x);fa[x]=y;} void cut(int x,int y) {makeroot(x);access(y);splay(y);if (ch[y][0]==x)fa[x]=0;} int query(int x,int y) {makeroot(x);access(y);splay(y);return mx[y];} void init() {memset(mx,-1,sizeof mx);} void modify(int x) {access(x);splay(x);col[x]^=1;update(x);} }lct; int n,q; int main() { freopen("in.txt","r",stdin); scanf("%d%d",&n,&q); lct.init(); for (int i=1;i<n;++i) { int x,y; scanf("%d%d",&x,&y); lct.link(x,y); } while (q--) { int op,v; scanf("%d%d",&op,&v); if (op==0) lct.modify(v); else printf("%d\n",lct.query(1,v)); } }