• 【BZOJ3065】带插入区间k小值


    题意:

    带插入,修改的区间k小值在线查询

    原序列长度<=35000,插入个数<=35000,修改个数<=70000,0<=权值<=70000

    题解:

    Orz vfleaking!!!

    显然这是道模板题,由于强制在线所以不能整体二分水过了qwq

    听说大量乱搞、分块、块状链表、暴力+卡常均可过……我写的hzwer树套树做法,就当锻炼码力吧qwq

    用替罪羊树维护原序列,每个点上维护一个权值线段树,查询时二分,码码码即可;

    线段树点数过多所以要写个内存池防止爆空间;

    时间复杂度$O(qlog^3n)$

    其实也不难写我就调了一下午+一晚上而已

    代码:

      1 #include<algorithm>
      2 #include<iostream>
      3 #include<cstring>
      4 #include<vector>
      5 #include<cstdio>
      6 #include<cmath>
      7 #include<queue>
      8 #define inf 2147483647
      9 #define eps 1e-9
     10 #define N 70000
     11 using namespace std;
     12 typedef long long ll;
     13 typedef double db;
     14 const db alpha=0.75;
     15 struct node{
     16     int ls,rs,v;
     17 }t[500001],tr[10000001];
     18 int n,q,x,y,k,rt,rb,ans=0,cnt=0,rts[70001],id[70001];
     19 char op[3];
     20 vector<int>vec,dl,qu;
     21 int newn(){
     22     if(!vec.size())return ++cnt;
     23     else{
     24         int ret=vec[vec.size()-1];
     25         vec.pop_back();
     26         return ret;
     27     }
     28 }
     29 bool bad(int u){
     30     return tr[rts[u]].v*alpha<=max(tr[rts[t[u].ls]].v,tr[rts[t[u].rs]].v);
     31 }
     32 void rec(int &u){
     33     vec.push_back(u);
     34     if(tr[u].ls)rec(tr[u].ls);
     35     if(tr[u].rs)rec(tr[u].rs);
     36     tr[u].v=0;
     37     u=0;
     38 }
     39 void del(int &u){
     40     rec(rts[u]);
     41     if(t[u].ls)del(t[u].ls);
     42     dl.push_back(u);
     43     if(t[u].rs)del(t[u].rs);
     44     u=0;
     45 }
     46 void updata(int &u,int l,int r,int p,int x){
     47     if(!u)u=newn();
     48     if(l==r){
     49         tr[u].v+=x;
     50         return;
     51     }
     52     int mid=(l+r)/2;
     53     if(p<=mid)updata(tr[u].ls,l,mid,p,x);
     54     else updata(tr[u].rs,mid+1,r,p,x);
     55     tr[u].v=tr[tr[u].ls].v+tr[tr[u].rs].v;
     56     if(!tr[u].v)rec(u);
     57 }
     58 void build(int &u,int l,int r){
     59     if(l>r)return;
     60     if(l==r){
     61         u=id[l];
     62         updata(rts[u],0,N,t[u].v,1);
     63         return;
     64     }
     65     int mid=(l+r)/2;
     66     u=id[mid];
     67     build(t[u].ls,l,mid-1);
     68     build(t[u].rs,mid+1,r);
     69     for(int i=l;i<=r;i++){
     70         updata(rts[u],0,N,t[id[i]].v,1);
     71     }
     72 }
     73 void rebuild(int &u){
     74     del(u);
     75     int sz=dl.size();
     76     for(int i=0;i<sz;i++)id[i+1]=dl[i];
     77     build(u,1,sz);
     78     dl.clear();
     79 }
     80 int update(int u,int p,int x){
     81     updata(rts[u],0,N,x,1);
     82     int ret;
     83     if(p==tr[rts[t[u].ls]].v+1){
     84         ret=t[u].v;
     85         t[u].v=x;
     86     }else if(tr[rts[t[u].ls]].v>=p){
     87         ret=update(t[u].ls,p,x);
     88     }else ret=update(t[u].rs,p-tr[rts[t[u].ls]].v-1,x);
     89     updata(rts[u],0,N,ret,-1);
     90     return ret;
     91 }
     92 void ins(int &u,int p,int x){
     93     if(!u){
     94         u=++n;
     95         updata(rts[u],0,N,x,1);
     96         t[u].v=x;
     97         return;
     98     }
     99     updata(rts[u],0,N,x,1);
    100     if(tr[rts[t[u].ls]].v>=p){
    101         ins(t[u].ls,p,x);
    102     }else ins(t[u].rs,p-tr[rts[t[u].ls]].v-1,x);
    103     if(bad(u))rb=u;
    104     else if(rb){
    105         if(rb==t[u].ls)rebuild(t[u].ls);
    106         else rebuild(t[u].rs);
    107         rb=0;
    108     }
    109 }
    110 void query(int u,int l,int r){
    111     int L=tr[rts[t[u].ls]].v,R=tr[rts[u]].v;
    112     if(l==1&&r==R){
    113         qu.push_back(rts[u]);
    114         return;
    115     }
    116     if(l<=L+1&&r>=L+1)dl.push_back(t[u].v);
    117     if(L>=r){
    118         query(t[u].ls,l,r);
    119     }else if(l>L+1)query(t[u].rs,l-L-1,r-L-1);
    120     else{
    121         if(l<=L)query(t[u].ls,l,L);
    122         if(L+1<R)query(t[u].rs,1,r-L-1);
    123     }
    124 }
    125 int Query(int l,int r,int k){
    126     query(rt,l,r);
    127     int tmp,L=0,R=N,sz1=qu.size(),sz2=dl.size();
    128     while(L<R){
    129         int mid=(L+R)/2;
    130         tmp=0;
    131         for(int i=0;i<sz1;i++){
    132             tmp+=tr[tr[qu[i]].ls].v;
    133         }
    134         for(int i=0;i<sz2;i++){
    135             if(L<=dl[i]&&dl[i]<=mid)tmp++;
    136         }
    137         if(tmp>k){
    138             for(int i=0;i<sz1;i++)qu[i]=tr[qu[i]].ls;
    139             R=mid;
    140         }else{
    141             for(int i=0;i<sz1;i++)qu[i]=tr[qu[i]].rs;
    142             L=mid+1;
    143             k-=tmp;
    144         }
    145     }
    146     qu.clear();
    147     dl.clear();
    148     return L;
    149 }
    150 int main(){
    151     scanf("%d",&n);
    152     for(int i=1;i<=n;i++){
    153         scanf("%d",&t[i].v);
    154         id[i]=i;
    155     }
    156     build(rt,1,n);
    157     scanf("%d",&q);
    158     while(q--){
    159         //for(int i=1;i<=n;i++)printf("%d ",rts[i]);
    160         //puts("");
    161         scanf("%s",op);
    162         if(op[0]=='M'){
    163             scanf("%d%d",&x,&k);
    164             x^=ans,k^=ans;
    165             update(rt,x,k);
    166         }else if(op[0]=='I'){
    167             scanf("%d%d",&x,&k);
    168             x^=ans,k^=ans;
    169             rb=0;
    170             ins(rt,x-1,k);
    171             if(rb)rb=0,rebuild(rt);
    172         }else{
    173             scanf("%d%d%d",&x,&y,&k);
    174             x^=ans,y^=ans,k^=ans;
    175             printf("%d
    ",ans=Query(x,y,k-1));
    176         }
    177     }
    178     return 0;
    179 } 
  • 相关阅读:
    77、Android设置虚线、圆角、渐变
    c# 制作自定义控件并生成dll文件旷展到其他项目使用
    VB ListView罗列图片
    (壹)、java面向对象详解
    php基本语法
    1.单例模式
    Memcached详解
    MySql的优化
    页面静态化详解
    mysql常用知识点
  • 原文地址:https://www.cnblogs.com/dcdcbigbig/p/10264083.html
Copyright © 2020-2023  润新知