洛谷P3038 [USACO11DEC]牧草种植Grass Planting

    xiaoxiao2021-03-25  96

    链接

      https://www.luogu.org/problem/show?pid=3038

    题解

      呃裸题....

      边化点然后LCT做就好了....没啥好说的

      当然正解肯定是树链剖分,可以用树状数组或者线段树维护。(以后有时间写一下树状数组的)

    代码

    //LCT #include <cstdio> #include <algorithm> #define maxn 500000 using namespace std; int N, M; struct node { int w, rev, add; node *f, *ch[2]; }nd[maxn], *s[maxn]; inline int getwh(node *x) {if(!x->f)return -1;if(x->f->ch[0]==x)return 0;if(x->f->ch[1]==x)return 1;return -1;} inline bool isroot(node *x){return getwh(x)==-1;} inline void join(node *x, node *y, int wh){if(x)x->f=y;if(y)y->ch[wh]=x;} inline void rev(node *x){if(x)x->rev^=1;} inline void add(node *x, int v){if(x)x->add+=v;} inline void pushdown(node *x) { if(x->rev) { swap(x->ch[0],x->ch[1]); rev(x->ch[0]),rev(x->ch[1]); x->rev=0; } if(x->add) { x->w+=x->add; add(x->ch[0],x->add),add(x->ch[1],x->add); x->add=0; } } inline void rotate(node *x) { node *y=x->f, *z=y->f; int c=getwh(x); if(isroot(y))x->f=y->f;else join(x,z,getwh(y)); join(x->ch[!c],y,c);join(y,x,!c); } inline void splay(node *x) { node *y; int top=0; for(y=x;!isroot(y);y=y->f)s[++top]=y;s[++top]=y; for(;top;top--)pushdown(s[top]); while(!isroot(x)) { y=x->f; if(isroot(y)){rotate(x);return;} if(getwh(x)^getwh(y))rotate(x);else rotate(y); rotate(x); } } inline void access(node *x) { node *t=0; while(x) { splay(x); x->ch[1]=t; t=x,x=x->f; } } inline void makeroot(node *x){access(x);splay(x);rev(x);} inline void link(node *x, node *y){makeroot(x);x->f=y;} int main() { int x, y, i; char t[5]; node *a, *b; scanf("%d%d",&N,&M); for(i=1;i<N;i++) { scanf("%d%d",&x,&y); if(x>y)swap(x,y); link(nd+N+i,nd+x),link(nd+N+i,nd+y); } for(i=1;i<=M;i++) { scanf("%s%d%d",t,&x,&y); if(*t=='P')makeroot(nd+x),access(nd+y),splay(nd+y),add(nd+y,1); else { a=nd+x, b=nd+y; makeroot(a);access(b);splay(b); pushdown(a->ch[1]); printf("%d\n",a->ch[1]->w); } } return 0; }
    转载请注明原文地址: https://ju.6miu.com/read-6832.html

    最新回复(0)