bzoj 3065: 带插入区间K小值 替罪羊树 && AC300
3065: 带插入区间K小值
Time Limit: 60 Sec Memory Limit: 512 MB
Submit: 1062 Solved: 253
[Submit][Status]
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 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
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组数据。
替罪羊树套线段树。
AC300怎么能刷水题?然后就做了这样一道题。第一次编替罪羊树,觉得比较恶心。这道题由于内存使用量很吓人,所以必须用垃圾回收,这类内存越界的问题很难检查出来,但是也有一些窍门,比如说我们可以通过改变数组大小,观察RE的位置是否相同,每次处理输出当前使用量来查看使用趋势。
这道题第一遍交RE,原因是有语句顺序问题导致一部分垃圾没有回收完全,内存超了。
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #include<algorithm>
- using namespace std;
- #define MAXN 80000
- #define MAXV 70007
- #define MAXT 30000000
- #define alpha 0.7
- struct sgt_node
- {
- int lc,rc,tot;
- }sgt[MAXT];
- int topt=;
- int stack2[MAXT];
- void Add_sgt(int &now,int l,int r,int pos,int delta)
- {
- if (!now)
- {
- int old=now;
- now=stack2[topt--];
- if (topt<)throw ;
- now=stack2[topt+];
- if (sgt[now].lc)stack2[++topt]=sgt[now].lc;
- if (sgt[now].rc)stack2[++topt]=sgt[now].rc;
- sgt[now]=sgt[old];
- }
- sgt[now].tot+=delta;
- if (l==r)return ;
- if (pos<=((l+r)>>))
- Add_sgt(sgt[now].lc,l,((l+r)>>),pos,delta);
- else
- Add_sgt(sgt[now].rc,((l+r)>>)+,r,pos,delta);
- if (sgt[now].tot==)
- {
- sgt[now].lc=sgt[now].rc=;
- stack2[++topt]=now;
- now=;
- }
- }
- int Qry_sgt(int &now,int l,int r,int x,int y)
- {
- if (!now)return ;
- if (l==x && r==y)return sgt[now].tot;
- int mid=(l+r)>>;
- if (y<=mid)
- return Qry_sgt(sgt[now].lc,l,mid,x,y);
- else if (mid<x)
- return Qry_sgt(sgt[now].rc,mid+,r,x,y);
- else return Qry_sgt(sgt[now].lc,l,mid,x,mid)+Qry_sgt(sgt[now].rc,mid+,r,mid+,y);
- }
- struct Scap_tree
- {
- int lc,rc;
- int val,root;
- int siz;
- }scp[MAXN];
- int tops=-,root=;
- int stack[MAXN];
- int *Add_scp(int &now,int pos,int v)
- {
- if (!now)
- {
- now=stack[tops--];
- if (tops<)throw ;
- scp[now].val=v;
- Add_sgt(scp[now].root,,MAXV,v,);
- scp[now].siz=;
- return NULL;
- }
- int* ret;
- if (pos==scp[scp[now].lc].siz+)
- ret=Add_scp(scp[now].lc,pos,v);
- else if (pos<=scp[scp[now].lc].siz)
- ret=Add_scp(scp[now].lc,pos,v);
- else
- ret=Add_scp(scp[now].rc,pos-scp[scp[now].lc].siz-,v);
- Add_sgt(scp[now].root,,MAXV,v,);
- scp[now].siz++;
- if (max(scp[scp[now].lc].siz,scp[scp[now].rc].siz)>scp[now].siz*alpha)
- return &now;
- return ret;
- }
- int Modify_scp(int now,int pos,int v)
- {
- Add_sgt(scp[now].root,,MAXV,v,);
- int t;
- if (scp[scp[now].lc].siz+==pos)
- {
- t=scp[now].val;
- Add_sgt(scp[now].root,,MAXV,t,-);
- scp[now].val=v;
- return t;
- }
- if (scp[scp[now].lc].siz>=pos)
- t=Modify_scp(scp[now].lc,pos,v);
- else
- t=Modify_scp(scp[now].rc,pos-scp[scp[now].lc].siz-,v);
- Add_sgt(scp[now].root,,MAXV,t,-);
- return t;
- }
- int vec[MAXN],topv=-;
- void Scan(int now)
- {
- if (!now)return ;
- Scan(scp[now].lc);
- vec[++topv]=scp[now].val;
- Scan(scp[now].rc);
- stack[++tops]=now;
- stack2[++topt]=scp[now].root;
- scp[now].siz=scp[now].lc=scp[now].rc=scp[now].val=scp[now].root=;
- }
- void Scan2(int now)
- {
- if (!now)return ;
- Scan2(scp[now].lc);
- printf("%d ",scp[now].val);
- Scan2(scp[now].rc);
- }
- void Build_scp(int &now,int l,int r)
- {
- if (l>r)return;
- now=stack[tops--];
- if (tops<)throw ;
- if (now>=MAXN)throw ;
- scp[now].val=vec[(l+r)>>];
- scp[now].root=;
- scp[now].siz=r-l+;
- for (int i=l;i<=r;i++)
- Add_sgt(scp[now].root,,MAXV,vec[i],);
- Build_scp(scp[now].lc,l,((l+r)>>)-);
- Build_scp(scp[now].rc,((l+r)>>)+,r);
- }
- void Rebuild(int &now)
- {
- if (&now==NULL)return ;
- topv=-;
- Scan(now);
- //for (int i=0;i<vec.size();i++)printf("%d ",vec[i]);printf("\n");
- Build_scp(now,,topv);
- }
- pair<int,int> lst[MAXN];
- int topl=-;
- void Search_scp(int now,int l,int d,bool f)
- {
- if (!l)return ;
- if (l==scp[now].siz)
- {
- lst[++topl]=make_pair(scp[now].root,d);
- return ;
- }
- if (f==)
- {
- if (scp[scp[now].lc].siz>=l)
- {
- Search_scp(scp[now].lc,l,d,false);
- }else
- {
- lst[++topl]=make_pair(scp[now].root,d);
- Search_scp(scp[now].rc,scp[now].siz-l,-d,true);
- }
- }else
- {
- if (scp[scp[now].rc].siz>=l)
- {
- Search_scp(scp[now].rc,l,d,true);
- }else
- {
- lst[++topl]=make_pair(scp[now].root,d);
- Search_scp(scp[now].lc,scp[now].siz-l,-d,false);
- }
- }
- }
- int Query_kth(int ll,int rr,int rank)
- {
- topl=-;
- Search_scp(root,ll-,-,false);
- Search_scp(root,rr,,false);
- int l=,r=MAXV;
- int mid;
- int sum;
- int i;
- while (l!=r)
- {
- mid=(l+r)>>;
- sum=;
- for (i=;i<=topl;i++)
- sum+=sgt[sgt[lst[i].first].lc].tot*lst[i].second;
- if (rank<=sum)
- {
- r=mid;
- for (i=;i<=topl;i++)
- lst[i].first=sgt[lst[i].first].lc;
- }else
- {
- rank-=sum;
- l=mid+;
- for (i=;i<=topl;i++)
- lst[i].first=sgt[lst[i].first].rc;
- }
- }
- return l;
- }
- int main()
- {
- // freopen("input.txt","r",stdin);
- // freopen("output.txt","w",stdout);
- int i,j,k,x,y,z,n,m;
- for (i=;i<MAXN;i++)stack[++tops]=i;
- for (i=;i<MAXT;i++)stack2[++topt]=i;
- scanf("%d",&n);
- for (i=;i<n;i++)
- {
- scanf("%d",&x);
- vec[++topv]=x;
- }
- Build_scp(root,,topv);
- scanf("%d\n",&m);
- //Scan2(root);printf("\n");
- char opt;
- int lastans=;
- for (i=;i<m;i++)
- {
- scanf("%c",&opt);
- if (i==)
- --++i;
- if (opt=='I')
- {
- scanf("%d %d\n",&x,&y);
- x^=lastans;y^=lastans;
- Rebuild(*Add_scp(root,x,y));
- }else if (opt=='M')
- {
- scanf("%d %d\n",&x,&y);
- x^=lastans;y^=lastans;
- Modify_scp(root,x,y);
- }else if (opt=='Q')
- {
- scanf("%d %d %d\n",&x,&y,&z);
- x^=lastans;y^=lastans;z^=lastans;
- printf("%d\n",lastans=Query_kth(x,y,z));
- }
- //printf("%d %d %d\n",i,tops,topt);
- }
- }
bzoj 3065: 带插入区间K小值 替罪羊树 && AC300的更多相关文章
- 【题解】BZOJ 3065: 带插入区间K小值——替罪羊树套线段树
题目传送门 题解 orz vfk的题解 3065: 带插入区间K小值 系列题解 一 二 三 四 惨 一开始用了一种空间常数很大的方法,每次重构的时候merge两颗线段树,然后无限RE(其实是MLE). ...
- BZOJ 3065 带插入区间K小值 (替罪羊树套线段树)
毒瘤题.参考抄自博客:hzwer 第一次写替罪羊树,完全是照着题解写的,发现这玩意儿好强啊,不用旋转每次都重构还能nlognnlognnlogn. 还有外面二分和里面线段树的值域一样,那么r = mi ...
- BZOJ 3065 带插入区间K小值(sag套线段树)
3065: 带插入区间K小值 Time Limit: 60 Sec Memory Limit: 512 MBSubmit: 4696 Solved: 1527[Submit][Status][Di ...
- 3065: 带插入区间K小值_树套树_替罪羊树_权值线段树
经过周六一天,周一3个小时的晚自习,周二2个小时的疯狂debug,终于凭借自己切掉了这道树套树题. Code: #include <cstdio> #include <algorit ...
- 【BZOJ3065】带插入区间K小值 替罪羊树+权值线段树
[BZOJ3065]带插入区间K小值 Description 从前有n只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力a[i].跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理 ...
- bzoj 3065: 带插入区间K小值(分块)
Description 从前有n只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力a[i].跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理性愉悦一下,查询区间k小值.他每次向它 ...
- 【bzoj3065】带插入区间K小值 替罪羊树套权值线段树
题目描述 从前有n只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力a[i].跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理性愉悦一下,查询区间k小值.他每次向它的随从伏特提出 ...
- BZOJ 3065 带插入区间K小值
http://www.lydsy.com/JudgeOnline/problem.php?id=3065 思路:替罪羊树套权值线段树. 当替罪羊树某个子树大于某个比利(比例)时就暴力重构,本题时间复杂 ...
- 【BZOJ】3065: 带插入区间K小值
http://www.lydsy.com/JudgeOnline/problem.php?id=3065 题意:带插入.修改的区间k小值在线查询.(原序列n<=35000, 询问<=175 ...
随机推荐
- Linux--------------安装mysql(2)
在 CentOS7 上安装 MySQL5.7 1 通过 SecureCRT 连接到阿里云 CentOS7 服务器: 2 进入到目录 /usr/local/ 中:cd /usr/local/ 3 创建目 ...
- Oracle--常见Exception
1. 错 误 名 称 错误代码 错 误 含 义 2. CURSOR_ALREADY_OPEN ORA_06511 试图打开已经打开的游标 3. INVALID_CURSOR ORA_ ...
- Struts,Spring,Hibernate的作用
Spring的作用: 在SSH框假中spring充当了管理容器的角色.我们都知道Hibernate用来做持久层,因 为它将JDBC做了一个良好的封装,程序员在与数据库进行交互时可以不用书写大量的SQL ...
- 一个react的完整项目展示
和一些人的关系像平行线,一辈子相守相望,见于眼底藏于心间.就怕耐不住寂寞,冲动而成了相交线,在一个点尽情拥抱,从此便离得越来越远,再也不见.遇到这样的人,因为不想做恋人只能一时,所以才选择做朋友能一世 ...
- 不需要软件让Windows7变身WIFI热点
很简单,就是把一台装有windows 7操作系统,并配有无线网卡的电脑变成一台无线路由器或无线AP,以便在没有路由器的环境中实现多台无线终端(比如支持wifi的手机.电脑等设备)共享无线网络.那么我们 ...
- Timestamp的作用及与字符串的相互转换 .
一.Timestamp的介绍 每一个数据库都有一个计数器,这个计数器记录着数据行的插入.更新行为.如果我们为一个表中增加 timestamp 列,那么,该列将记录每一个数据行的计数器值.假如数据库中当 ...
- mysqldump: unknown option '--no-beep'
想要备份mysql数据库时,输入mysqldump命令出现如题所示的错误,在网上找了好久,终于从一个帖子上得到了一些提示,就动手试了下,嘿 还真成了!! mysqldump --no-default ...
- selenium2.0处理case实例(一)
通过自动化脚本, 判断下拉框选项值是否按照字母顺序(忽略大小写)显示 case场景如下: 1)打开www.test.com;2)判断下拉框选项是否按照字母顺序排列(忽略大小写)3)选择其中一个任意选项 ...
- OS X环境下SVN回滚工程到指定版本,回滚指定文件到指定版本
1.打开命令行终端 2.cd + 工程或文件目录 3.svn update 工程目录或文件目录 -r 版本号 在Xcode中选中文件,右键选择''show in finder''(也可以用快捷键,不过 ...
- 初尝seajs,只提供自己学习做笔记
(仅供自己使用,勿喷) 闲着无聊,尝试下seajs, 只是在公司项目上随便添加并测试了一下,做下记录, 方便以后自己使用更快的上手: 下载最新的sea.js, v- 3.0.0 新建seajsConf ...