• 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('
    ')); RI ptop=0;
                while (x) pt[++ptop]=x%10,x/=10; while (ptop) pc(pt[ptop--]+48); pc('
    ');
            }
            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;
    }
    
  • 相关阅读:
    【转】final 关键字
    【转】安装Fiddler2+JsonViewer插件
    【转】SAP SD定价技术分析
    【转】SAP PP 顾问面试考试试题及资料
    【转】Hibernate数据过滤
    【转】与计划有关的生产数据
    【转】销售凭证类别
    将MyEclipse中的项目导入到Eclipse中报错的解决放法,将项目打war包部署服务器
    查看Android下生成的.db数据库
    删除快速启动栏的快捷方式 pplive
  • 原文地址:https://www.cnblogs.com/cjjsb/p/10821315.html
Copyright © 2020-2023  润新知