BZOJ 3110 [Zjoi2013]K大数查询(整体二分)
3110: [Zjoi2013]K大数查询
Time Limit: 20 Sec Memory Limit: 512 MB
Submit: 11654 Solved: 3505
[Submit][Status][Discuss]
Description
有N个位置,M个操作。操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c
如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少。
Input
第一行N,M
接下来M行,每行形如1 a b c或2 a b c
Output
输出每个询问的结果
Sample Input
1 1 2 1
1 1 2 2
2 1 1 2
2 1 1 1
2 1 2 3
Sample Output
2
1
HINT
【样例说明】
第一个操作 后位置 1 的数只有 1 , 位置 2 的数也只有 1 。 第二个操作 后位置 1
的数有 1 、 2 ,位置 2 的数也有 1 、 2 。 第三次询问 位置 1 到位置 1 第 2 大的数 是
1 。 第四次询问 位置 1 到位置 1 第 1 大的数是 2 。 第五次询问 位置 1 到位置 2 第 3
大的数是 1 。
N,M<=50000,N,M<=50000
a<=b<=N
1操作中abs(c)<=N
2操作中c<=Maxlongint
题解
求第K大。
然后我们把权值设为n-c+1;
最后答案为n-ans+1就把问题转化为了第k小
不过这题是插入。其实不是很难毕竟只是把权值小于mid的数的位置都加一就行了,我们把修改二分和一个位置多少个权值没有关系。
和以前唯一的区别就是这次是整体修改,用线段树就行了(就是慢)
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const long long N=;
struct query{
long long type,x,y,w,id;
}q[N],c2[N],c1[N];
long long ans[N],m,n,tot;
struct tree{
long long l,r,lazy,sum;
}tr[N*];
void update(long long now){
tr[now].sum=tr[now*].sum+tr[now*+].sum;
}
void pushdown(long long now){
if(tr[now].lazy==)return;
tr[now*].sum+=(tr[now*].r-tr[now*].l+)*tr[now].lazy;
tr[now*+].sum+=(tr[now*+].r-tr[now*+].l+)*tr[now].lazy;
tr[now*].lazy+=tr[now].lazy;
tr[now*+].lazy+=tr[now].lazy;
tr[now].lazy=;
}
void build(long long l,long long r,long long now){
tr[now].l=l;tr[now].r=r;
if(l==r)return;
long long mid=(l+r)>>;
build(l,mid,now*);
build(mid+,r,now*+);
}
void add(long long l,long long r,long long c,long long now){
pushdown(now);
if(tr[now].l==l&&tr[now].r==r){
tr[now].sum+=(tr[now].r-tr[now].l+)*c;
tr[now].lazy+=c;
return;
}
long long mid=(tr[now].l+tr[now].r)>>;
if(l>mid)add(l,r,c,now*+);
else if(r<=mid)add(l,r,c,now*);
else{
add(l,mid,c,now*);
add(mid+,r,c,now*+);
}
update(now);
}
long long check(long long l,long long r,long long now){
pushdown(now);
if(tr[now].l==l&&tr[now].r==r){
return tr[now].sum;
}
long long mid=(tr[now].l+tr[now].r)>>;
if(l>mid)return check(l,r,now*+);
else if(r<=mid)return check(l,r,now*);
else return check(l,mid,now*)+check(mid+,r,now*+);
}
void solve(long long l,long long r,long long L,long long R){
if(l>r)return ;
if(L==R){
for(long long i=l;i<=r;i++){
if(q[i].type==)ans[q[i].id]=L;
}
return;
}
long long mid=(L+R)>>;
long long lnow=;long long rnow=;
for(long long i=l;i<=r;i++){
if(q[i].type==){
if(q[i].w<=mid){
add(q[i].x,q[i].y,,);
c1[++lnow]=q[i];
}
else c2[++rnow]=q[i];
}
else{
long long tmp=check(q[i].x,q[i].y,);
if(tmp>=q[i].w)c1[++lnow]=q[i];
else{
q[i].w-=tmp;
c2[++rnow]=q[i];
}
}
}
for(long long i=;i<=lnow;i++){
if(c1[i].type==)add(c1[i].x,c1[i].y,-,);
}
for(long long i=;i<=lnow;i++){
q[l+i-]=c1[i];
}
for(long long i=;i<=rnow;i++){
q[l+lnow+i-]=c2[i];
}
solve(l,l+lnow-,L,mid);
solve(l+lnow,r,mid+,R);
}
int main(){
scanf("%lld%lld",&n,&m);
build(,n,);
for(long long i=;i<=m;i++){
long long k,a,b,c;
scanf("%lld%lld%lld%lld",&k,&a,&b,&c);
if(k==){
q[i].type=;q[i].x=a;q[i].y=b;q[i].w=n-c+;
}
else{
q[i].type=;q[i].x=a;q[i].y=b;q[i].w=c;q[i].id=++tot;
}
}
solve(,m,-n,n);
for(long long i=;i<=tot;i++){
printf("%lld\n",n-ans[i]+);
}
return ;
}
BZOJ 3110 [Zjoi2013]K大数查询(整体二分)的更多相关文章
- BZOJ.3110.[ZJOI2013]K大数查询(整体二分 树状数组/线段树)
题目链接 BZOJ 洛谷 整体二分求的是第K小(利用树状数组).求第K大可以转为求第\(n-K+1\)小,但是这样好像得求一个\(n\). 注意到所有数的绝对值\(\leq N\),将所有数的大小关系 ...
- BZOJ 3110: [Zjoi2013]K大数查询 [整体二分]
有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少. N ...
- BZOJ 3110 [Zjoi2013]K大数查询 ——整体二分
[题目分析] 整体二分显而易见. 自己YY了一下用树状数组区间修改,区间查询的操作. 又因为一个字母调了一下午. 貌似树状数组并不需要清空,可以用一个指针来维护,可以少一个log 懒得写了. [代码] ...
- BZOJ 3110 [ZJOI2013]K大数查询 (整体二分+线段树)
和dynamic rankings这道题的思想一样 只不过是把树状数组换成线段树区间修改,求第$K$大的而不是第$K$小的 这道题还有负数,需要离散 #include <vector> # ...
- BZOJ 3110: [Zjoi2013]K大数查询 [树套树]
3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 6050 Solved: 2007[Submit][Sta ...
- bzoj 3110: [Zjoi2013]K大数查询 树状数组套线段树
3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1384 Solved: 629[Submit][Stat ...
- 树套树专题——bzoj 3110: [Zjoi2013] K大数查询 & 3236 [Ahoi2013] 作业 题解
[原题1] 3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MB Submit: 978 Solved: 476 Descri ...
- BZOJ 3110: [Zjoi2013]K大数查询( 树状数组套主席树 )
BIT+(可持久化)权值线段树, 用到了BIT的差分技巧. 时间复杂度O(Nlog^2(N)) ---------------------------------------------------- ...
- BZOJ 3110([Zjoi2013]K大数查询-区间第k大[段修改,在线]-树状数组套函数式线段树)
3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MB Submit: 418 Solved: 235 [ Submit][ ...
随机推荐
- 关于输入getline
此函数可读取整行,包括前导和嵌入的空格,并将其存储在字符串对象中. getline 函数如下所示: getline(cin, inputLine); 其中 cin 是正在读取的输入流,而 inputL ...
- NPOI简单的给某个单元格字体设置颜色
参考文档有: https://www.cnblogs.com/gossip/p/4307486.html https://bbs.csdn.net/topics/391042064?page=1 效果 ...
- swift语言点评十六-Initialization && Deinitialization
initial value:必须初始化.不影响观察者 Classes and structures must set all of their stored properties to an appr ...
- layui层级
zIndex:layer.zIndex, success : function(layero){ var zIndex = layer.index; $(layero).css(‘z-index’,z ...
- 修改maven打包名字
仅需在pom.xml添加下列配置 build> <finalName>userapi</finalName> </build>
- BZOJ 2565 最长双回文串(回文自动机)
题意 给一个长度为N的字符串S.对于一个字符串AB,如果A和B都是回文串,那么称AB是一个双回文串.求问S最长双回文子串的长度?N <= 100000 题解 正反双向构造回文自动机,得到某一个点 ...
- 【BZOJ 1257】[CQOI2007]余数之和
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] k%i=k-(k/i)i 则∑k%i = nk-∑(k/i)*i 因为k/i是整除运算. 所以会有某一段连续的i,它们的k/i的值都 ...
- Java NIO笔记(一):NIO介绍
Java NIO即Java Non-blocking IO(Java非堵塞I/O),由于是在Jdk1.4之后添加的一套新的操作I/O工具包,所以通常会被叫做Java New IO.NIO是为提供I/O ...
- springMVC 配置jdbcTemplate连接Oracle数据库出错
springMVC 配置jdbcTemplate连接Oracle数据库出错 错误信息: log4j:WARN No appenders could be found for logger (org.s ...
- 【推荐系统实战】:C++实现基于用户的协同过滤(UserCollaborativeFilter)
好早的时候就打算写这篇文章,可是还是參加阿里大数据竞赛的第一季三月份的时候实验就完毕了.硬生生是拖到了十一假期.自己也是醉了... 找工作不是非常顺利,希望写点东西回想一下知识.然后再攒点人品吧,仅仅 ...