zoukankan      html  css  js  c++  java
  • P5283 [十二省联考2019]异或粽子

    传送门

    超级钢琴+可持久化$Trie$

    同样设三元组 $(o,l,r)$ 表示左端点为 $o$,右端点 $in [l,r]$ 的区间的最大异或值,这个东西可以用可持久化 $Trie$ 来维护

    一开始把所有 $(i,i,n)$ 扔到堆里,然后每次取出计算贡献,设取得最大异或值的位置为 $t$,然后再把 $(o,l,t-1)$ 和 $(o,t+1,r)$ 扔到堆里

    具体还是看代码,很容易理解

    注意可能爆 $int$,所以要开 $unsigned int$,要注意代码常数

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    using namespace std;
    typedef long long ll;
    typedef unsigned int uint;
    inline uint read()
    {
        uint x=0; char ch=getchar();
        while(ch<'0'||ch>'9') ch=getchar();
        while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return x;
    }
    const int N=1e6+7,M=1e7+7e6;
    uint n,K,sum[N],rt[N],t[M],pos[M],c[M][2];
    namespace Trie {
        uint cnt=0;
        void ins(uint &o,int p,uint pre,uint v,uint ps)
        {
            o=++cnt; t[o]=t[pre]+1;
            if(p<0) { pos[o]=ps; return; }
            int d=(v>>p)&1; c[o][d^1]=c[pre][d^1];
            ins(c[o][d],p-1,c[pre][d],v,ps);
        }
        uint query(uint o,int p,uint pre,uint v)
        {
            if(p<0) return pos[o];
            int d=(v>>p)&1;
            if(t[c[o][d^1]]-t[c[pre][d^1]]>0) return query(c[o][d^1],p-1,c[pre][d^1],v);
            else return query(c[o][d],p-1,c[pre][d],v);
        }
    }
    struct dat {
        uint o,l,r,t;
        dat (uint o,uint l,uint r) : o(o),l(l),r(r),t(Trie::query(rt[r],31,rt[l-1],sum[o-1])) {}
        inline bool operator < (const dat &tmp) const {
            return (sum[t]^sum[o-1])<(sum[tmp.t]^sum[tmp.o-1]);
        }
    };
    priority_queue <dat> Q;
    ll ans;
    int main()
    {
        n=read(),K=read(); uint a;
        Trie::ins(rt[0],31,0,0,0);
        for(int i=1;i<=n;i++)
        {
            a=read(); sum[i]=sum[i-1]^a;
            Trie::ins(rt[i],31,rt[i-1],sum[i],i);
        }
        for(int i=1;i<=n;i++) Q.push(dat(i,i,n));
        while(K--)
        {
            dat T=Q.top(); ans+=(sum[T.t]^sum[T.o-1]); Q.pop();
            if(T.l<T.t) Q.push(dat(T.o,T.l,T.t-1));
            if(T.r>T.t) Q.push(dat(T.o,T.t+1,T.r));
        }
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    2.16 C++类与new和delete操作符
    2.15 C++常量指针this
    2.14 C++析构函数
    2.13 C++拷贝构造函数
    2.12 C++ explicit关键字详解
    2.11 C++转型构造函数
    2.10 C++利用构造函数限制对象的创建
    2.9 C++使用默认参数的构造函数
    2.8 C++参数初始化表
    linux 查看进程启动路径
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/10682774.html
Copyright © 2011-2022 走看看