zoukankan      html  css  js  c++  java
  • 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);
                 }
             }
         }
    }
  • 相关阅读:
    程序设计实践读书笔记(一)
    Markdown语法和MWeb使用说明
    Comparable和Comparator的学习笔记
    WMware给centos6.8虚拟机添加硬盘
    Centos定时自动执行脚本
    linux开机关机自启动或自关闭服务的方式
    jira从windows迁移到linux
    ERROR: transport error 202:bind failed:Address already in use
    linux文件备份到windows方法
    validator验证
  • 原文地址:https://www.cnblogs.com/xuanyiming/p/8457955.html
Copyright © 2011-2022 走看看