【BZOJ 2157】旅游
再水一道模板题,明天就要出发去参加二轮省选了赶紧复习复习模板。
链剖模板题,可是写链剖太麻烦了,还是写lct吧。
但这个lct比较麻烦了,因为边权有正有负,要统计最大值和最小值,这样点权赋为什么值都会妨碍统计。
想了半天,后来发现自己脑抽了,统计的时候特判一下当前点是点还是边不就可以了吗?
裸的模板题调了好久啊,因为后来往原先错误的程序加上上述特判时总是漏这漏那,以后一定要认真思考每个细节确保无误后再开始写代码,这样脑子里有一个清晰的框架,写起来更快,而且不容易出错,大大节省了调试的时间。切忌边想边写!!!这样写到最后会有很多bug,而且对于程序的每个函数的作用会比较模糊。
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 20003; const int inf = 0x7fffffff; void read(int &k) { k = 0; int fh = 1; char c = getchar(); for(; c < '0' || c > '9'; c = getchar()) if (c == '-') fh = -1; for(; c >= '0' && c <= '9'; c = getchar()) k = (k << 1) + (k << 3) + c - '0'; k = k * fh; } struct node *null; struct node { node *ch[2], *fa; int d, mx, mn, sum; bool edge; short rev, change; bool pl() {return fa->ch[1] == this;} void setc(node *r, bool c) {ch[c] = r; r->fa = this;} bool check() {return fa == null || (fa->ch[0] != this && fa->ch[1] != this);} void upd() {if (this == null) return; sum = -sum; d = -d; swap(mx, mn); mx = -mx; mn = -mn;} void push() { if (rev) {rev = 0; swap(ch[0], ch[1]); ch[0]->rev ^= 1; ch[1]->rev ^= 1;} if (change) { change = 0; ch[0]->change ^= 1; ch[1]->change ^= 1; ch[0]->upd(); ch[1]->upd(); } } void count() { sum = ch[0]->sum + ch[1]->sum; mx = max(ch[0]->mx, ch[1]->mx); mn = min(ch[0]->mn, ch[1]->mn); if (edge) mx = max(mx, d), mn = min(mn, d), sum += d; } } pool[N + N], *p[N], *E[N]; namespace LCT { void rotate(node *r) { node *f = r->fa; bool c = r->pl(); if (f->check()) r->fa = f->fa; else f->fa->setc(r, f->pl()); f->setc(r->ch[!c], c); r->setc(f, !c); f->count(); } void update(node *r) {if (!r->check()) update(r->fa); r->push();}; void splay(node *r) { update(r); for(; !r->check(); rotate(r)) if (!r->fa->check()) rotate(r->pl() == r->fa->pl() ? r->fa : r); r->count(); } node *access(node *r) { node *y = null; for(; r != null; y = r, r = r->fa) splay(r), r->ch[1] = y; return y; } void changert(node *r) {access(r)->rev ^= 1; splay(r);} void link(node *r, node *t) {changert(r); r->fa = t;} int tot = 0; node *newnode(int num, bool flag) { node *t = &pool[++tot]; t->ch[0] = t->ch[1] = t->fa = null; t->d = t->sum = num; t->rev = t->change = 0; t->edge = flag; if (flag) t->mx = t->mn = num; else t->mx = -inf, t->mn = inf; return t; } void Build(int n) { null = new node; null->ch[0] = null->ch[1] = null->fa = null; null->mx = -inf; null->mn = inf; null->rev = null->change = null->edge = null->d = null->sum = 0; for(int i = 0; i < n; ++i) p[i] = newnode(0, 0); } } int n, m; int main() { read(n); LCT::Build(n); int u, v, e, x, y; for(int i = 1; i < n; ++i) { read(u); read(v); read(e); E[i] = LCT::newnode(e, 1); LCT::link(p[u], E[i]); LCT::link(p[v], E[i]); } read(m); char c[3]; for(int i = 1; i <= m; ++i) { scanf("%s", c); read(u); read(v); switch (c[0]) { case 'C': LCT::splay(E[u]); E[u]->d = v; E[u]->count(); break; case 'N': LCT::changert(p[u]); LCT::access(p[v]); LCT::splay(p[v]); p[v]->upd(); p[v]->change ^= 1; break; case 'S': LCT::changert(p[u]); LCT::access(p[v]); LCT::splay(p[v]); printf("%d\n", p[v]->sum); break; case 'M': LCT::changert(p[u]); LCT::access(p[v]); LCT::splay(p[v]); if (c[1] == 'A') printf("%d\n", p[v]->mx); else printf("%d\n", p[v]->mn); break; } } return 0; }
SDOI 2016 Round2 Day-1 Bless All,祝CreationAugust,TA,morestep,Vampire,Sunshine,Lcomyn,Rivendell学长们和fye学姐都进队!
NOI 2017 Bless All