bzoj 3217: ALOEXT 替罪羊树套trie

题意

给你一个数列,要求资瓷四个操作:
插入一个数
删除一个数
修改一个数
给出一个区间[l,r],设w为区间内第二大,问w与区间内元素异或的最大值。
n,m<=100000,元素大小小于2^20,强制在线

分析

都是套路题。直接外层替罪羊树内层trie就好了。注意要垃圾回收。
第一次写替罪羊树的删除操作。一开始想的是用删除节点的后继来替代删除节点,然后写的我一度开始怀疑人生。后来才知道替罪羊树的删除一般是伪删除,也就是在该节点上打上删除标记,然后不进行查找操作即可。在重建的时候再把那些节点去掉就好了。

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;

const int N=200005;

int n,m,sz,top,stack[N],rt,root[N],bin[25],a[5],R,n0;
struct tree{int l,r,s,size,del,fa,val,mx1,mx2;}t[N];
vector<int> p,q;

int read()
{
    int x=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

struct Trie
{
    int sz;
    vector<int> re;
    struct tree{int s,l,r;}t[30000005];

    int newnode()
    {
        if (!re.size()) return ++sz;
        else {int x=re.back();re.pop_back();return x;}
    }

    void reuse(int &d)
    {
        if (!d) return;
        if (t[d].l) reuse(t[d].l);
        if (t[d].r) reuse(t[d].r);
        t[d].s=0;re.push_back(d);d=0;
    }

    void ins(int &d,int x,int y,int z)
    {
        if (!d) d=newnode();t[d].s+=z;
        if (x==-1) return;
        if (!(y&bin[x])) ins(t[d].l,x-1,y,z);
        else ins(t[d].r,x-1,y,z);
    }

    int query(int d,int x,int y)
    {
        if (x==-1) return 0;
        if (y&bin[x]) return t[t[d].l].s?query(t[d].l,x-1,y)+bin[x]:query(t[d].r,x-1,y);
        else return t[t[d].r].s?query(t[d].r,x-1,y)+bin[x]:query(t[d].l,x-1,y);
    }
}tr;

void updata(int d)
{
    t[d].size=t[t[d].l].size+t[t[d].r].size+1;
    t[d].s=t[t[d].l].s+t[t[d].r].s+1-t[d].del;
    a[0]=t[d].val;a[1]=t[t[d].l].mx1;a[2]=t[t[d].l].mx2;
    a[3]=t[t[d].r].mx1;a[4]=t[t[d].r].mx2;
    sort(a,a+5);
    t[d].mx1=a[4];t[d].mx2=a[3];
}

void build(int &d,int l,int r)
{
    if (l>r) {d=0;return;}
    int mid=(l+r)/2;d=stack[mid];
    build(t[d].l,l,mid-1);if (t[d].l) t[t[d].l].fa=d;
    build(t[d].r,mid+1,r);if (t[d].r) t[t[d].r].fa=d;
    updata(d);
    for (int i=l;i<=r;i++) tr.ins(root[d],19,t[stack[i]].val,1);
}

void dfs(int x)
{
    tr.reuse(root[x]);
    if (t[x].l) dfs(t[x].l);
    if (!t[x].del) stack[++top]=x;
    if (t[x].r) dfs(t[x].r);
}

void rebuild(int d)
{
    int tmp=t[d].fa,op=(d==t[tmp].l?0:1);
    top=0;dfs(d);build(d,1,top);
    if (!tmp) {t[d].fa=0;rt=d;return;}
    else
    {
        t[d].fa=tmp;
        if (!op) t[tmp].l=d;
        else t[tmp].r=d;
    }
}

void ins(int &d,int x,int y)
{
    if (!d) {d=++sz;t[d].val=y;tr.ins(root[d],19,y,1);updata(d);return;}
    tr.ins(root[d],19,y,1);
    if (t[d].del)
        if (t[t[d].l].s>=x) ins(t[d].l,x,y),t[t[d].l].fa=d;
        else ins(t[d].r,x-t[t[d].l].s,y),t[t[d].r].fa=d;
    else if (t[t[d].l].s+1>=x) ins(t[d].l,x,y),t[t[d].l].fa=d;
    else ins(t[d].r,x-t[t[d].l].s-1,y),t[t[d].r].fa=d;
    updata(d);
    if (t[d].size*0.75<max(t[t[d].l].size,t[t[d].r].size)) R=d;
}

int del(int &d,int x)
{
    int w;
    if (t[d].del) w=t[t[d].l].s>=x?del(t[d].l,x):del(t[d].r,x-t[t[d].l].s);
    else if (t[t[d].l].s+1==x) {w=t[d].val;t[d].val=0;tr.ins(root[d],19,w,-1);t[d].del=1;updata(d);return w;}
    else w=t[t[d].l].s+1>x?del(t[d].l,x):del(t[d].r,x-t[t[d].l].s-1);
    tr.ins(root[d],19,w,-1);updata(d);
    return w;
}

int modify(int &d,int x,int y)
{
    int w;tr.ins(root[d],19,y,1);
    if (t[d].del) w=t[t[d].l].s>=x?modify(t[d].l,x,y):modify(t[d].r,x-t[t[d].l].s,y);
    else if (t[t[d].l].s+1==x) {w=t[d].val;t[d].val=y;tr.ins(root[d],19,w,-1);updata(d);return w;}
    else w=t[t[d].l].s+1>x?modify(t[d].l,x,y):modify(t[d].r,x-t[t[d].l].s-1,y);
    tr.ins(root[d],19,w,-1);updata(d);
    return w;
}

void get(int d,int l,int r)
{
    if (l>r) return;
    if (l==1&&t[d].s==r) {p.push_back(d);return;}
    int x=t[t[d].l].s,y=t[d].s;
    if (!t[d].del&&l<=x+1&&r>=x+1) q.push_back(d);
    get(t[d].l,l,min(x,r));get(t[d].r,max(1,l-x-1+t[d].del),r-x-1+t[d].del);
}

int solve(int l,int r)
{
    p.clear();q.clear();get(rt,l,r);
    int mx1=0,mx2=0;
    for (int i=0;i<p.size();i++)
    {
        a[0]=mx1;a[1]=mx2;a[2]=t[p[i]].mx1;a[3]=t[p[i]].mx2;
        sort(a,a+4);
        mx1=a[3];mx2=a[2];
    }
    for (int i=0;i<q.size();i++)
        if (t[q[i]].val>mx1) mx2=mx1,mx1=t[q[i]].val;
        else if (t[q[i]].val>mx2) mx2=t[q[i]].val;
    int ans=0;
    for (int i=0;i<q.size();i++) ans=max(ans,mx2^t[q[i]].val);
    for (int i=0;i<p.size();i++) ans=max(ans,tr.query(root[p[i]],19,mx2));
    return ans;
}

int main()
{
    bin[0]=1;
    for (int i=1;i<=20;i++) bin[i]=bin[i-1]*2;
    n=read();m=read();n0=n;sz=n;
    for (int i=1;i<=n;i++)
    {
        int x=read();t[i].val=x;
    }
    for (int i=1;i<=n;i++) stack[++top]=i;
    build(rt,1,n);
    int ans=0;
    while (m--)
    {
        char ch[2];scanf("%s",ch);
        if (ch[0]=='I')
        {
            int x=(read()+ans)%n0+1,y=(read()+ans)%1048576;
            ins(rt,x,y);n0++;
            if (R) rebuild(R),R=0;
        }
        else if (ch[0]=='D')
        {
            int x=(read()+ans)%n0+1;
            del(rt,x);n0--;
        }
        else if (ch[0]=='C')
        {
            int x=(read()+ans)%n0+1,y=(read()+ans)%1048576;
            modify(rt,x,y);
        }
        else
        {
            int l=(read()+ans)%n0+1,r=(read()+ans)%n0+1;
            printf("%d\n",ans=solve(l,r));
        }
    }
    return 0;
}
    原文作者:Trie树
    原文地址: https://blog.csdn.net/qq_33229466/article/details/78732062
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞