bzoj3065

题解:

替罪羊树

(讲道理昨天讲课我一点都听不懂)

alpha取到0.75比较好(当然啦可能其他的更好)

每当不满足条件的时候就重构

代码:

#include<bits/stdc++.h>
using namespace std;
const double alpha=0.75;
const int N=10000005,M=100005;
int tmp,n,m,sz,lastans,root,v[M],dfn[M],rt[M],ls[M],rs[M];
struct seg{int l,r,sum;}a[N];
vector<int> rec,t,p;
inline int newnode()
{
    if (!rec.size())return ++sz;
    else 
      {
        int k=rec.back();
        rec.pop_back();
        return k;
     }
}
void reclaim(int &x)
{
    if (!x)return;
    rec.push_back(x);
    reclaim(a[x].l);
    reclaim(a[x].r);
    a[x].sum=0;x=0;
}
void insert(int &k,int l,int r,int val,int f)
{
    if (!k)k=newnode();
    if (l==r)
     {
         a[k].sum+=f;
        return;
     }
    int mid=(l+r)>>1;
    if (val<=mid)insert(a[k].l,l,mid,val,f);
    else insert(a[k].r,mid+1,r,val,f);
    a[k].sum=a[a[k].l].sum+a[a[k].r].sum;
    if (!a[k].sum)reclaim(k);
}
void build(int &k,int l,int r)
{
    if (l>r)return;
    if (l==r)
     {
        k=dfn[l];
        insert(rt[k],0,70000,v[k],1);
        return;
     }
    int mid=(l+r)>>1;
    k=dfn[mid];
    build(ls[k],l,mid-1);
    build(rs[k],mid+1,r);
    for (int i=l;i<=r;i++)insert(rt[k],0,70000,v[dfn[i]],1);
}
void del(int &x)
{
    if(!x)return;
    reclaim(rt[x]);
    del(ls[x]);
    p.push_back(x);
    del(rs[x]);
    x=0;
}
void rebuild(int &x)
{
    del(x);
    int s1=p.size();
    for (int i=1;i<=s1;i++)dfn[i]=p[i-1];
    build(x,1,s1);
    p.clear();
}
int modify(int k,int x,int val)
{
    insert(rt[k],0,70000,val,1);
    int t,L=a[rt[ls[k]]].sum;
    if (L+1==x){t=v[k];v[k]=val;}    
    else if (L>=x)t=modify(ls[k],x,val);
    else t=modify(rs[k],x-L-1,val);
    insert(rt[k],0,70000,t,-1);
    return t;
}
void query(int k,int l,int r)
{
    int L=a[rt[ls[k]]].sum,R=a[rt[k]].sum;
    if (l==1&&r==R){t.push_back(rt[k]);return;}
    if (l<=L+1&&r>=L+1)p.push_back(v[k]);
    if (r<=L)query(ls[k],l,r);
    else if (l>L+1)query(rs[k],l-L-1,r-L-1);
    else 
     {
        if (l<=L)query(ls[k],l,L);
        if (R>L+1)query(rs[k],1,r-L-1);
     }
}
int solve_query(int L,int R,int K)
{
    query(root,L,R);
    K--;
    int l=0,r=70000,s1=t.size(),s2=p.size();
    while(l<r)
     {
        int mid=(l+r)>>1,sum=0;
        for (int i=0;i<s1;i++)sum+=a[a[t[i]].l].sum;
        for (int i=0;i<s2;i++)
         if(p[i]>=l&&p[i]<=mid)sum++;
        if (K<sum)
         {
            for (int i=0;i<s1;i++)t[i]=a[t[i]].l;
            r=mid;
         }
        else 
         {
            for (int i=0;i<s1;i++)t[i]=a[t[i]].r;
            l=mid+1;K-=sum;
         }
     }
    t.clear();p.clear();
    return l;
}
void insert(int &k,int x,int val)
{
    if (!k)
     {
        k=++n;
        insert(rt[k],0,70000,val,1);
        v[k]=val;
        return;
     }
    insert(rt[k],0,70000,val,1);
    int L=a[rt[ls[k]]].sum;
    if (L>=x)insert(ls[k],x,val);
    else insert(rs[k],x-L-1,val);
    if (a[rt[k]].sum*alpha>max(a[rt[ls[k]]].sum,a[rt[rs[k]]].sum))
     {
         if (tmp)
           {
            if (ls[k]==tmp)rebuild(ls[k]);
            else rebuild(rs[k]);
            tmp=0;
           }
     }
    else tmp=k;
}
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)scanf("%d",&v[i]);
    for (int i=1;i<=n;i++)dfn[i]=i;
    build(root,1,n);
    scanf("%d",&m);
    char s[2];
    int x,y,k;
    while (m--)
     {
         scanf("%s",&s);
         scanf("%d%d",&x,&y);
         x^=lastans;y^=lastans;
         if (s[0]=='Q')
          {
              scanf("%d",&k);
              k^=lastans;
              lastans=solve_query(x,y,k);
              printf("%d
",lastans);
         }
        if (s[0]=='M')modify(root,x,y);
        if (s[0]=='I')
         {
             tmp=0;
             insert(root,x-1,y);
             if (tmp)
              {
                  tmp=0;
                  rebuild(root);
             }
         }
     }
}
原文地址:https://www.cnblogs.com/xuanyiming/p/8457955.html