洛谷P1501 [国家集训队]Tree II(BZOJ2631)

LCT

洛谷题目传送门
BZOJ题目传送门

记一个乘标记和一个加标记来维护。如果打过维护区间乘和加操作的线段树的话这道题就很轻松了,但是LCT因为会动还要维护一个size。其它都是一些细节,如下传乘标记时也要修改加标记,下传加标记时和要乘上size什么的。

代码:

#include<cctype>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100005
#define F inline
#define V F void
using namespace std;
typedef unsigned int uint;
const uint p=51061;
struct tree{ int to[2],fa,f; uint a,m,x,s,sz; }t[N];
int n,q,stk[N],tp;
F char readc(){
    static char buf[100000],*l=buf,*r=buf;
    if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
    return l==r?EOF:*l++;
}
#define pd(c) (c!='+'&&c!='-'&&c!='*'&&c!='/')
F int _read(){
    int x=0; char ch=readc();
    while (!isdigit(ch)&&pd(ch)) ch=readc();
    if (!pd(ch)) return ch;
    while (isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=readc();
    return x;
}
V writec(int x){ if (x>9) writec(x/10); putchar(x%10+48); }
V _write(int x){ writec(x),puts(""); }
#define rt(x) (t[t[x].fa].to[0]!=x&&t[t[x].fa].to[1]!=x)
V pshp(int x){
    t[x].sz=t[t[x].to[0]].sz+t[t[x].to[1]].sz+1;
    t[x].s=(t[t[x].to[0]].s+t[t[x].to[1]].s+t[x].x)%p;
}
V pshm(int x,uint m){ (t[x].m*=m)%=p,(t[x].a*=m)%=p,(t[x].x*=m)%=p,(t[x].s*=m)%=p; }
V psha(int x,uint a){ (t[x].a+=a)%=p,(t[x].x+=a)%=p,(t[x].s+=t[x].sz*a%p)%=p; }
V pshd(int x){
    int &l=t[x].to[0],&r=t[x].to[1]; uint m=t[x].m,a=t[x].a;
    if (m!=1) pshm(l,m),pshm(r,m),t[x].m=1;
    if (a) psha(l,a),psha(r,a),t[x].a=0;
    if (t[x].f) t[x].f^=1,t[l].f^=1,t[r].f^=1,swap(l,r);
}
V rtt(int x){
    int y=t[x].fa,z=t[y].fa,l=t[y].to[0]==x;
    if (!rt(y)) t[z].to[t[z].to[0]!=y]=x;
    t[x].fa=z,t[y].fa=x,t[t[x].to[l]].fa=y;
    t[y].to[l^1]=t[x].to[l],t[x].to[l]=y;
    pshp(y),pshp(x);
}
V splay(int x){
    for (int i=stk[tp=1]=x;!rt(i);i=t[i].fa) stk[++tp]=t[i].fa;
    while (tp) pshd(stk[tp--]);
    for (int y=t[x].fa,z=t[y].fa;!rt(x);rtt(x),y=t[x].fa,z=t[y].fa)
        if (!rt(y)) rtt((t[z].to[0]==y^t[y].to[0]==x)?x:y);
}
V ccss(int x){
    for (int i=0;x;i=x,x=t[x].fa)
        splay(x),t[x].to[1]=i,pshp(x);
}
V mkrt(int x){ ccss(x),splay(x),t[x].f^=1; }
V sprt(int x,int y){ mkrt(x),ccss(y),splay(y); }
V lnk(int x,int y){ mkrt(x),t[x].fa=y; }
V cut(int x,int y){ sprt(x,y); t[y].to[0]=t[x].fa=0; }
int main(){
    n=_read(),q=_read();
    for (int i=1;i<=n;i++) t[i].m=t[i].sz=t[i].x=1;
    for (int i=1,x,y;i<n;i++)
        x=_read(),y=_read(),lnk(x,y);
    while (q--){
        int f=_read(),x=_read(),y=_read();
        switch (f){
            case '+': sprt(x,y),psha(y,_read()); break;
            case '-': cut(x,y),x=_read(),y=_read(),lnk(x,y); break;
            case '*': sprt(x,y),pshm(y,_read()); break;
            case '/': sprt(x,y),_write(t[y].s); break;
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/a1799342217/article/details/81303629