Time Limit: 60 Sec  Memory Limit: 512 MB
Submit: 3436  Solved: 1103

Description

从前有n只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力a[i]。跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴。这时跳蚤国王决定理性愉悦一下,查询区间k小值。他每次向它的随从伏特提出这样的问题: 从左往右第x个到第y个跳蚤中,a[i]第k小的值是多少。
这可难不倒伏特,他在脑袋里使用函数式线段树前缀和的方法水掉了跳蚤国王的询问。
这时伏特发现有些跳蚤跳久了弹跳力会有变化,有的会增大,有的会减少。
这可难不倒伏特,他在脑袋里使用树状数组套线段树的方法水掉了跳蚤国王的询问。(orz 主席树)
这时伏特发现有些迟到的跳蚤会插入到这一行的某个位置上,他感到非常生气,因为……他不会做了。
请你帮一帮伏特吧。
快捷版题意:带插入、修改的区间k小值在线查询。

Input

第一行一个正整数n,表示原来有n只跳蚤排成一行做早操。
第二行有n个用空格隔开的非负整数,从左至右代表每只跳蚤的弹跳力。
第三行一个正整数q,表示下面有多少个操作。
下面一共q行,一共三种操作对原序列的操作:(假设此时一共m只跳蚤)
1. Q x y k: 询问从左至右第x只跳蚤到从左至右第y只跳蚤中,弹跳力第k小的跳蚤的弹跳力是多少。
    (1 <= x <= y <= m, 1 <= k <= y - x + 1)
2. M x val: 将从左至右第x只跳蚤的弹跳力改为val。
    (1 <= x <= m)
3. I x val: 在从左至右第x只跳蚤的前面插入一只弹跳力为val的跳蚤。即插入后从左至右第x只跳蚤是我刚插入的跳蚤。
    (1 <= x <= m + 1)

为了体现在线操作,设lastAns为上一次查询的时候程序输出的结果,如果之前没有查询过,则lastAns = 0。
则输入的时候实际是:
Q _x _y _k ------> 表示 Q _x^lastAns _y^lastAns _k^lastAns
M _x _val  ------> 表示 M _x^lastAns _val^lastAns
I _x _val  ------> 表示 I _x^lastAns _val^lastAns
简单来说就是操作中输入的整数都要异或上一次询问的结果进行解码。

(祝Pascal的同学早日转C++,就不提供pascal版的描述了。)

Output

对于每个询问输出回答,每行一个回答。

Sample Input

10
10 5 8 28 0 19 2 31 1 22
30
I 6 9
M 1 11
I 8 17
M 1 31
M 6 26
Q 2 7 6
I 23 30
M 31 7
I 22 27
M 26 18
Q 26 17 31
I 5 2
I 18 13
Q 3 3 3
I 27 19
Q 23 23 30
Q 5 13 5
I 3 0
M 15 27
Q 0 28 13
Q 3 29 11
M 2 8
Q 12 5 7
I 30 19
M 11 19
Q 17 8 29
M 29 4
Q 3 0 12
I 7 18
M 29 27

Sample Output

28
2
31
0
14
15
14
27
15
14

HINT

此题作为一个小小的研究来搞吧~做法有很多~不知道这题究竟有多少种做法。

请自觉O(log^2n),我故意卡块状链表,块链A了的请受我深情一拜……

A掉的同学请在Discuss里面简要说下自己的做法吧~

原序列长度 <= 35000

插入个数 <= 35000,修改个数 <= 70000,查询个数 <= 70000  ,0 <= 每时每刻的权值 <= 70000

由于是OJ上的题,所以数据无梯度。为了防止卡OJ,本题只有4组数据。

Source

作者 vfleaking

树 树套树 替罪羊树套权值线段树

非旋转的平衡树是可以套在别的树外面的。

用替罪羊树维护序列,替罪羊树上塞一堆权值线段树维护区间内有哪些值。

查询的时候,把该区间对应的线段树区间都拎出来,一起二分找第k小。

查询方法学自黄学长

注意替罪羊树重建的时候,要按照中序遍历回收节点,能省一个排序操作。

应该用线段树合并来着,然而听说合并写得不够好的话和暴力重建一个速度,那我就直接暴力重建了

刷了一页WA

  1 /*by SilverN*/
  2 #include<iostream>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<cstdio>
  6 #include<cmath>
  7 #include<vector>
  8 using namespace std;
  9 //const int MXN=10000010;
 10 const int mxn=150010;
 11 const int MX=70000;
 12 int read(){
 13     int x=0,f=1;char ch=getchar();
 14     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 15     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
 16     return x*f;
 17 }
 18 struct SGT{
 19     int l,r;
 20     int smm;
 21 }sg[mxn<<6];
 22 int scnt=0;
 23 int st[mxn<<6],top=0;
 24 int rot[mxn];
 25 inline int newnode(){
 26     if(top){
 27         int tmp=st[top--];
 28         sg[tmp].l=sg[tmp].r=sg[tmp].smm=0;
 29         return tmp;
 30     }
 31     return ++scnt;
 32 }
 33 inline void pushup(int rt){
 34     sg[rt].smm=sg[sg[rt].l].smm+sg[sg[rt].r].smm;return;
 35 }
 36 void del(int &rt){//线段树回收结点
 37     if(!rt)return;
 38     if(sg[rt].l)del(sg[rt].l);
 39     if(sg[rt].r)del(sg[rt].r);
 40     st[++top]=rt; rt=0;
 41     return;
 42 }
 43 void update(int v,int p,int l,int r,int &rt){
 44     if(!rt)rt=newnode();
 45     if(l==r){sg[rt].smm+=v;return;}
 46     int mid=(l+r)>>1;
 47     if(p<=mid)update(v,p,l,mid,sg[rt].l);
 48     else update(v,p,mid+1,r,sg[rt].r);
 49     pushup(rt);
 50     if(!sg[rt].smm)del(rt);
 51     return;
 52 }
 53 //
 54 struct node{
 55     int l,r;
 56     int val,sz;
 57 }t[mxn];
 58 int n,Q;
 59 int cnt=0,ROT;
 60 int flag=0,fafa=0;//重构标记
 61 int w[mxn];
 62 int bnode[mxn],bct=0;
 63 int dfn[mxn],dtime=0;
 64 void Build(int l,int r,int &rt){
 65     if(l>r){rt=0;return;}
 66     if(l==r){
 67         rt=dfn[l];
 68         update(1,t[rt].val,0,MX,rot[rt]);
 69         t[rt].sz=1;
 70         return;
 71     }
 72     int mid=(l+r)>>1;
 73     rt=dfn[mid];
 74     Build(l,mid-1,t[rt].l); Build(mid+1,r,t[rt].r);
 75     for(int i=l;i<=r;i++)//建线段树
 76         update(1,t[dfn[i]].val,0,MX,rot[rt]);
 77     t[rt].sz=t[t[rt].l].sz+t[t[rt].r].sz+1;
 78     return;
 79 }
 80 void DEL(int &x){//删除替罪羊树结点
 81     if(!x)return;
 82     del(rot[x]);//删除对应线段树
 83     DEL(t[x].l);
 84     bnode[++bct]=x;//中序遍历删除
 85     DEL(t[x].r);
 86     t[x].sz=0;
 87     x=0;
 88     return;
 89 }
 90 void Rebuild(int &x){
 91     DEL(x);
 92     for(int i=1;i<=bct;i++)dfn[i]=bnode[i];
 93     Build(1,bct,x);
 94     bct=0;//clear
 95     return;
 96 }
 97 void insert(int v,int k,int &rt){
 98     if(!rt){
 99         rt=++n;
100         t[rt].val=v;
101         t[rt].sz=1;
102         update(1,t[rt].val,0,MX,rot[rt]);
103         return;
104     }
105     update(1,v,0,MX,rot[rt]);
106 /*  int L=sg[rot[t[rt].l]].smm;
107     if(L>=k)insert(v,k,t[rt].l);
108     else insert(v,k-L-1,t[rt].r);*/
109     if(t[t[rt].l].sz<k)insert(v,k-t[t[rt].l].sz-1,t[rt].r);
110         else insert(v,k,t[rt].l);
111     t[rt].sz=t[t[rt].l].sz+t[t[rt].r].sz+1;
112 //  int R=sg[rot[rt]].smm;
113 //  if(L/(double)R>0.75 || L/(double)R<0.2)flag=rt;
114     if(t[t[rt].l].sz/(double)t[rt].sz>0.72 || t[t[rt].l].sz/(double)t[rt].sz<0.25)flag=rt;
115     if(flag==t[rt].l || flag==t[rt].r)fafa=rt;
116     return;
117 }
118 int change(int v,int k,int rt){
119 //  printf("change:%d %d %d\n",v,k,rt);
120     update(1,v,0,MX,rot[rt]);
121     int tmp=0;//查找旧值
122 /*  int L=sg[rot[t[rt].l]].smm;
123     if(L+1==k){tmp=t[rt].val;t[rt].val=v;}
124     else if(L>=k)tmp=change(v,k,t[rt].l);
125     else tmp=change(v,k-L-1,t[rt].r);*/
126     if(t[t[rt].l].sz+1==k){
127         tmp=t[rt].val;t[rt].val=v;
128     }
129     else if(t[t[rt].l].sz>=k)tmp=change(v,k,t[rt].l);
130         else tmp=change(v,k-t[t[rt].l].sz-1,t[rt].r);
131     update(-1,tmp,0,MX,rot[rt]);//删除旧值
132     return tmp;
133 }
134 vector<int>qt,qp;//区间 单点
135 void query(int L,int R,int x){//在平衡树上收集区间
136 //  if(!x)return;
137     int ls=t[x].l,rs=t[x].r;
138     int l=sg[rot[ls]].smm,r=sg[rot[x]].smm;
139     //当前结点包含区间
140     if(L==1 && R==r){qt.push_back(rot[x]);return;}
141     if(L<=l+1 && l+1<=R) qp.push_back(t[x].val);
142     if(R<=l)query(L,R,t[x].l);
143     else if(L>l+1)query(L-(l+1),R-(l+1),t[x].r);
144     else{
145         if(L<=l)query(L,l,t[x].l);
146         if(r>l+1)query(1,R-l-1,t[x].r);
147     }
148     return;
149 }
150 int Query(int L,int R,int K){
151     query(L,R,ROT);
152     K--;
153     int l=0,r=MX,s1=qt.size(),s2=qp.size();
154     while(l<r){//二分答案
155         int mid=(l+r)>>1,smm=0;
156         for(int i=0;i<s1;i++)smm+=sg[sg[qt[i]].l].smm;//区间
157         for(int i=0;i<s2;i++)//单点
158             if(l<=qp[i] && qp[i]<=mid)smm++;
159         if(K<smm){
160             for(int i=0;i<s1;i++)qt[i]=sg[qt[i]].l;
161             r=mid;
162         }
163         else{
164             for(int i=0;i<s1;i++)qt[i]=sg[qt[i]].r;
165             l=mid+1;K-=smm;
166         }
167     }
168     qt.clear();qp.clear();
169     return l;
170 }
171 int lastans=0;
172 int main(){
173 //  freopen("in.txt","r",stdin);
174     int i,j;
175     n=read();
176     for(i=1;i<=n;i++)w[i]=read();
177     for(i=1;i<=n;i++)dfn[i]=i,t[i].val=w[i];
178     Build(1,n,ROT);
179     Q=read();
180     char op[2];int x,y,k;
181     while(Q--){
182         scanf("%s",op);
183         switch(op[0]){
184             case 'Q':{
185                 x=read()^lastans;y=read()^lastans;k=read()^lastans;
186 //              x=read();y=read();k=read();
187                 lastans=Query(x,y,k);
188                 printf("%d\n",lastans);
189                 break;
190             }
191             case 'M':{
192                 x=read()^lastans;k=read()^lastans;
193 //              x=read();k=read();
194                 change(k,x,ROT);
195                 break;
196             }
197             case 'I':{
198                 x=read()^lastans;k=read()^lastans;
199 //              x=read();k=read();
200                 flag=0;fafa=0;
201                 insert(k,x-1,ROT);
202                 if(flag){
203                     if(flag==ROT)Rebuild(ROT);
204                     else if(t[fafa].l==flag)Rebuild(t[fafa].l);
205                         else if(t[fafa].r==flag)Rebuild(t[fafa].r);
206                 }
207                 break;
208             }
209         }
210     }
211     return 0;
212 }

转载于:https://www.cnblogs.com/SilverNebula/p/6777290.html

Bzoj3065 带插入区间K小值相关推荐

  1. BZOJ-3065 带插入区间K小值

    替罪羊树套权值线段树,其中替罪羊树可以满足插入的操作. #include <cstdlib> #include <cstdio> #include <algorithm& ...

  2. 【题解】BZOJ 3065: 带插入区间K小值——替罪羊树套线段树

    题目传送门 题解 orz vfk的题解 3065: 带插入区间K小值 系列题解 一 二 三 四 惨 一开始用了一种空间常数很大的方法,每次重构的时候merge两颗线段树,然后无限RE(其实是MLE). ...

  3. P4278 带插入区间K小值

    题目链接 题目描述 快捷版题意:带插入.修改的区间k小值在线查询. 输入格式 第一行一个正整数nnn,表示原来有nnn只跳蚤排成一行做早操. 第二行有nnn个用空格隔开的非负整数,从左至右代表每只跳蚤 ...

  4. 【bzoj3065】: 带插入区间K小值 详解——替罪羊套函数式线段树

    不得不说,做过最爽的树套树---- 由于有了区间操作,我们很容易把区间看成一棵平衡树,对他进行插入,那么外面一层就是平衡树了,这就与我们之前所见到的不同了.我们之前所见到的大多数是线段树套平衡树而此题 ...

  5. 【luogu3834】【模板】可持久化线段树 2(主席树),静态区间第K小值

    problem solution 题目:有n个数,多次询问一个区间[L,R]中第k小的值是多少. 思路: 查询[1,n]中的第k小值: 先对数据进行离散化,然后按值域建立线段树,线段树中维护某个值域中 ...

  6. hdu 2665(主席树查询区间k大值)

    先贴我自己写的代码做模板虽然跟原博主没什么两样.(一开始空间开的4*maxn,交到hdu上一直TLE很奇怪) #include<bits/stdc++.h> using namespace ...

  7. 4923: [Lydsy1706月赛]K小值查询 平衡树 非旋转Treap

    国际惯例的题面: 这种维护排序序列,严格大于的进行操作的题都很套路...... 我们按照[0,k],(k,2k],(2k,inf)分类讨论一下就好. 显然第一个区间的不会变化,第二个区间的会被平移进第 ...

  8. HDU3949 XOR (线性基、查找第k小值)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 我们用高斯消元求出的a1,a2,-,ana_1,a_2, \dots,a_na1​,a2​,-,an​ ...

  9. COGS-930-找第k小的数-HNOI2012-主席树

    描述 静态区间第k小值 分析 改了一个主席树的模板, 改成了数组版. 感觉数组的要简洁好多. 主席树的讲解:http://hi.baidu.com/lov_zyf/item/87b578342e73f ...

  10. 【HDU3949 + BZOJ2115 + CF724G】【异或线性基例题】| 倍增 | 第k小异或和 | DFS处理环 |【CGWR】| N

    三道关于异或线性基的有趣的题目 [1] HDU 3949. XOR Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/3276 ...

最新文章

  1. mysql 实时聚合分析,mysql累积聚合原理与用法实例分析
  2. Syszuxpin中文输入法移植
  3. 缓存cache和缓冲区buffer
  4. python init函数_在Python中解释类__init __()函数内部和外部的变量。
  5. zookeeper 密码_阿里资深JAVA架构带你深度剖析dubbo和zookeeper关系
  6. python图形化编程工具哪个好_mPython(图形化编程软件) V0.5.0 官方版
  7. 工作总结 项目中如何处理重复提交问题
  8. centOS6.6虚拟机启动后登陆界面无法显示
  9. ie8 不支持 position:fixed 的简单解决办法
  10. 深度学习TensorFlow生产环境部署(模型部署篇)
  11. 2019.7.2刷题统计
  12. 解决 fast api “detail“: “There was an error parsing the body“问题
  13. DNS的作用是什么?为什么一定要配置DNS才能上网
  14. Git —— 4、团队协作机制及GitHub操作
  15. 他人的数据挖掘面试题-经验
  16. 脉冲响应与频率响应的关系
  17. 如何将多个PDF文件合并为一个PDF文件?PDF文件合并教程
  18. python爬虫课设报告_python爬虫小说设计报告 相关实例(示例源码)下载 - 好例子网...
  19. 参与微软Docs翻译
  20. 链表中快慢指针的应用

热门文章

  1. 基于axis2的webservice和android简单的本地数据交互(下)
  2. 最让人心动的十大互联网界广告语+超笑评语
  3. pytnon 学习day-1
  4. linux私有ftp搭建与创建新用户
  5. BZOJ3674: 可持久化并查集加强版
  6. 【bzoj1999】[Noip2007]Core树网的核 树的直径+双指针法+单调队列
  7. JAVA基础——Java 中必须了解的常用类
  8. deepin安装mysql记录
  9. VC++2012编程演练数据结构《14》链式堆栈
  10. struts2 使用Validation框架进行数据验证