bzoj 5495: [2019省队联测]异或粽子【可持久化trie+大根堆】

时间:2019-04-15
本文章向大家介绍bzoj 5495: [2019省队联测]异或粽子【可持久化trie+大根堆】,主要包括bzoj 5495: [2019省队联测]异或粽子【可持久化trie+大根堆】使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

和bzoj4504差不多,就是换了个数据结构
像超级钢琴一样把五元组放进大根堆,每次取一个出来拆开,(d,l,r,p,v)表示右端点为d,左端点区间为(l,r),最大区间和值为v左端点在p上
关于怎么快速求区间和,用一个可持久trie上维护最大xor值和对应的点即可

#include<iostream>
#include<cstdio>
#include<queue>
//#include<ctime>
using namespace std;
const int N=500005;
int n,m,rt[N],tot;
unsigned int a[N],s[N],b[35];
long long ans;
struct trie
{
    int c[2],s,p;
}t[20000005];
struct qwe
{
    int d,l,r,p;
    unsigned int v;
    qwe(int D=0,int L=0,int R=0,int P=0,unsigned int V=0)
    {
        d=D,l=L,r=R,p=P,v=V;
    }
    bool operator < (const qwe &a) const
    {
        return v<a.v;
    }
};
priority_queue<qwe>q;
long long read()
{
    long long r=0,f=1;
    char p=getchar();
    while(p>'9'||p<'0')
    {
        if(p=='-')
            f=-1;
        p=getchar();
    }
    while(p>='0'&&p<='9')
    {
        r=r*10+p-48;
        p=getchar();
    }
    return r*f;
}
void ins(int &ro,int la,int w,int id)
{
    ro=++tot;
    t[ro]=t[la];
    t[ro].s++;
    if(w==-1)
    {
        t[ro].p=id;
        return;
    }
    bool p=(s[id]&b[w]);//cerr<<w<<" "<<p<<endl;
    ins(t[ro].c[p],t[la].c[p],w-1,id);
}
pair<int,unsigned int>ques(int la,int ro,int id,int w,unsigned int v)
{//cerr<<t[ro].s-t[la].s<<endl;
    if(w==-1)
        return make_pair(t[ro].p,v);
    bool p=(s[id]&b[w]);//cerr<<w<<" "<<p<<" "<<t[t[ro].c[p^1]].s<<" "<<t[t[la].c[p^1]].s<<endl;
    if(t[t[ro].c[p^1]].s-t[t[la].c[p^1]].s>0)
        return ques(t[la].c[p^1],t[ro].c[p^1],id,w-1,v|b[w]);
    else
        return ques(t[la].c[p],t[ro].c[p],id,w-1,v);
}
int main()
{
    // freopen("xor.in","r",stdin);
    // freopen("xor.out","w",stdout);
    n=read(),m=read();
    for(int i=1;i<=n;i++)
        a[i]=read();
    b[0]=1;
    for(int i=1;i<=31;i++)
        b[i]=(b[i-1]<<1);
    for(int i=n;i>=1;i--)
        s[i]=s[i+1]^a[i];
    rt[0]=++tot;
    for(int i=1;i<=n;i++)
        ins(rt[i],rt[i-1],31,i);//cerr<<"OK"<<endl;
    for(int i=1;i<=n;i++)
    {
        pair<int,unsigned int>nw=ques(rt[0],rt[i],i+1,31,0);
        q.push(qwe(i,1,i,nw.first,nw.second));
    }
    while(m--)
    {
        qwe u=q.top();//cerr<<u.v<<endl;
        q.pop();
        ans+=u.v;
        if(u.l<=u.p-1)
        {
            pair<int,unsigned int>nw=ques(rt[u.l-1],rt[u.p-1],u.d+1,31,0);
            q.push(qwe(u.d,u.l,u.p-1,nw.first,nw.second));
        }
        if(u.p+1<=u.r)
        {
            pair<int,unsigned int>nw=ques(rt[u.p],rt[u.r],u.d+1,31,0);
            q.push(qwe(u.d,u.p+1,u.r,nw.first,nw.second));
        }
    }//cerr<<clock()<<endl;
    printf("%lld\n",ans);
    return 0;
}