Luogu P5352 Terrible Homework

神仙@TheLostWeak出的题,因为他最近没时间所以我先写一下sol(其实我也没什么时间)

作为一道简单的数据结构题想必大家都能看出必须用LCT维护信息吧

一个朴素的想法就是直接维护四种操作的值,但是这样修改除了异或好像都不能维护

既然一个\(\log\)不可行那么就大力两个\(\log\)吧,很容易想到直接把信息拆分成二进制来存,然后记一下子树内所有数每一位上\(1\)的个数和

同时我们再维护一个子树大小,那么对于每种询问时直接大力枚举每一位的情况判断即可:

  • and:判断这一位上\(1\)的个数是否等于子树大小
  • or:判断这一位上是否有\(1\)
  • xor:判断这一位上\(1\)的个数的奇偶性
  • sum:大力累加起来就好了

具体的,修改的时候由于是异或操作,因此直接把对应要变的那一位\(0,1\)的个数调换,即用子树大小减去\(1\)的个数

然后还需要下传标记,这个直接lazy tag维护一下就好了,类似于Luogu P1501 [国家集训队]Tree II

然后我们就把这道水水的送分题写完了,LCT由于是板子所以会比较长,其实是核心代码是很短的

CODE

#include<cstdio>
#include<cctype>
#define RI register int
#define CI const int&
#define Tp template <typename T>
using namespace std;
typedef long long LL;
const int N=100005,RG=30;
int n,m,val[N],x,y,z; char opt;
class FileInputOutput
{
    private:
        static const int S=1<<21;
        #define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,S,stdin),A==B)?EOF:*A++)
        #define pc(ch) (Ftop<S?Fout[Ftop++]=ch:(fwrite(Fout,1,S,stdout),Fout[(Ftop=0)++]=ch))
        char Fin[S],Fout[S],*A,*B; int Ftop,pt[25];
    public:
        Tp inline void read(T& x)
        {
            x=0; char ch; while (!isdigit(ch=tc()));
            while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));
        }
        inline void get_alpha(char& ch)
        {
            while (!isalpha(ch=tc()));
        }
        Tp inline void write(T x)
        {
            if (!x) return (void)(pc('0'),pc('\n')); RI ptop=0;
            while (x) pt[++ptop]=x%10,x/=10; while (ptop) pc(pt[ptop--]+48); pc('\n');
        }
        inline void Fend(void)
        {
            fwrite(Fout,1,Ftop,stdout);
        }
        #undef tc
        #undef pc
}F;
class Link_Cut_Tree
{
    private:
        struct splay
        {
            int ch[2],fa,s[RG],size,tag; bool rev;
        }node[N]; int stack[N],top;
        #define lc(x) node[x].ch[0]
        #define rc(x) node[x].ch[1]
        #define fa(x) node[x].fa
        #define S(x,y) node[x].s[y]
        #define SZ(x) node[x].size
        #define R(x) node[x].rev
        #define T(x) node[x].tag
        inline void swap(int& x,int& y)
        {
            int t=x; x=y; y=t;
        }
        inline void rever(CI now)
        {
            swap(lc(now),rc(now)); R(now)^=1;
        }
        inline void upt(CI now,CI xv)
        {
            for (RI i=0;i<RG;++i) if ((xv>>i)&1)
            S(now,i)=SZ(now)-S(now,i); val[now]^=xv; T(now)^=xv;
        }
        inline void pushup(CI now)
        {
            SZ(now)=SZ(lc(now))+SZ(rc(now))+1; for (RI i=0;i<RG;++i)
            S(now,i)=S(lc(now),i)+S(rc(now),i)+((val[now]>>i)&1);
        }
        inline void pushdown(CI now)
        {
            if (R(now)) rever(lc(now)),rever(rc(now)),R(now)=0;
            if (T(now)) upt(lc(now),T(now)),upt(rc(now),T(now)),T(now)=0;
        }
        inline int identify(CI now)
        {
            return rc(fa(now))==now;
        }
        inline void connect(CI x,CI y,CI d)
        {
            node[fa(x)=y].ch[d]=x;
        }
        inline bool isroot(CI now)
        {
            return lc(fa(now))!=now&&rc(fa(now))!=now;
        }
        inline void rotate(CI now)
        {
            int x=fa(now),y=fa(x),d=identify(now); if (!isroot(x)) node[y].ch[identify(x)]=now;
            fa(now)=y; connect(node[now].ch[d^1],x,d); connect(x,now,d^1); pushup(x); pushup(now);
        }
        inline void splay(int now)
        {
            int t=now; while (stack[++top]=t,!isroot(t)) t=fa(t);
            while (top) pushdown(stack[top--]); for (;!isroot(now);rotate(now))
            t=fa(now),!isroot(t)&&(rotate(identify(now)!=identify(t)?now:t),0);
        }
        inline void access(int x)
        {
            for (int y=0;x;x=fa(y=x)) splay(x),rc(x)=y,pushup(x);
        }
        inline void makeroot(CI now)
        {
            access(now); splay(now); rever(now);
        }
        inline int findroot(int now)
        {
            for (access(now),splay(now);lc(now);now=lc(now)) pushdown(now); return splay(now),now;
        }
        inline void split(CI x,CI y)
        {
            makeroot(x); access(y); splay(y);
        }
    public:
        inline void build(void)
        {
            for (RI i=1;i<=n;++i) for (RI j=0;j<RG;++j) S(i,j)=(val[i]>>j)&1;
        }
        inline void link(CI x,CI y)
        {
            makeroot(x); if (findroot(y)!=x) fa(x)=y;
        }
        inline void cut(CI x,CI y)
        {
            makeroot(x); if (findroot(y)==x&&fa(y)==x&&!lc(y)) rc(x)=fa(y)=0; pushup(x);
        }
        inline void modify_xor(CI x,CI y,CI z)
        {
            split(x,y); upt(y,z);
        }
        inline int query_and(CI x,CI y,int ret=0)
        {
            split(x,y); for (RI i=0;i<RG;++i)
            if (S(y,i)==SZ(y)) ret|=1<<i; return ret;
        }
        inline int query_or(CI x,CI y,int ret=0)
        {
            split(x,y); for (RI i=0;i<RG;++i)
            if (S(y,i)) ret|=1<<i; return ret;
        }
        inline int query_xor(CI x,CI y,int ret=0)
        {
            split(x,y); for (RI i=0;i<RG;++i)
            if (S(y,i)&1) ret|=1<<i; return ret;
        }
        inline LL query_sum(CI x,CI y,LL ret=0)
        {
            split(x,y); for (RI i=0;i<RG;++i)
            ret+=1LL*(1<<i)*S(y,i); return ret;
        }
        #undef lc
        #undef rc
        #undef fa
        #undef S
        #undef SZ
        #undef R
        #undef T
}LCT;
int main()
{
    //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    RI i; for (F.read(n),F.read(m),i=1;i<=n;++i) F.read(val[i]);
    for (LCT.build(),i=1;i<=m;++i)
    {
        F.get_alpha(opt); F.read(x); F.read(y);
        switch (opt)
        {
            case 'L':
                LCT.link(x,y); break;
            case 'C':
                LCT.cut(x,y); break;
            case 'U':
                F.read(z); LCT.modify_xor(x,y,z); break;
            case 'A':
                F.write(LCT.query_and(x,y)); break;
            case 'O':
                F.write(LCT.query_or(x,y)); break;
            case 'X':
                F.write(LCT.query_xor(x,y)); break;
            case 'S':
                F.write(LCT.query_sum(x,y)); break;
        }
    }
    return F.Fend(),0;
}
posted @ 2019-05-06 18:34  空気力学の詩  阅读(238)  评论(0编辑  收藏  举报