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

2 5
1 1 2 1
1 1 2 2
2 1 1 2
2 1 1 1
2 1 2 3

Sample Output

1
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大数查询(整体二分)的更多相关文章

  1. BZOJ.3110.[ZJOI2013]K大数查询(整体二分 树状数组/线段树)

    题目链接 BZOJ 洛谷 整体二分求的是第K小(利用树状数组).求第K大可以转为求第\(n-K+1\)小,但是这样好像得求一个\(n\). 注意到所有数的绝对值\(\leq N\),将所有数的大小关系 ...

  2. BZOJ 3110: [Zjoi2013]K大数查询 [整体二分]

    有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少. N ...

  3. BZOJ 3110 [Zjoi2013]K大数查询 ——整体二分

    [题目分析] 整体二分显而易见. 自己YY了一下用树状数组区间修改,区间查询的操作. 又因为一个字母调了一下午. 貌似树状数组并不需要清空,可以用一个指针来维护,可以少一个log 懒得写了. [代码] ...

  4. BZOJ 3110 [ZJOI2013]K大数查询 (整体二分+线段树)

    和dynamic rankings这道题的思想一样 只不过是把树状数组换成线段树区间修改,求第$K$大的而不是第$K$小的 这道题还有负数,需要离散 #include <vector> # ...

  5. BZOJ 3110: [Zjoi2013]K大数查询 [树套树]

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6050  Solved: 2007[Submit][Sta ...

  6. bzoj 3110: [Zjoi2013]K大数查询 树状数组套线段树

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1384  Solved: 629[Submit][Stat ...

  7. 树套树专题——bzoj 3110: [Zjoi2013] K大数查询 &amp; 3236 [Ahoi2013] 作业 题解

    [原题1] 3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 978  Solved: 476 Descri ...

  8. BZOJ 3110: [Zjoi2013]K大数查询( 树状数组套主席树 )

    BIT+(可持久化)权值线段树, 用到了BIT的差分技巧. 时间复杂度O(Nlog^2(N)) ---------------------------------------------------- ...

  9. BZOJ 3110([Zjoi2013]K大数查询-区间第k大[段修改,在线]-树状数组套函数式线段树)

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec   Memory Limit: 512 MB Submit: 418   Solved: 235 [ Submit][ ...

随机推荐

  1. luogu 2869 挑剔的美食家

    Gourmet Grazers 传送门 题目大意 约翰的奶牛对食物越来越挑剔了.现在,商店有\(M\) 份牧草可供出售,奶牛食量很大,每份牧草仅能供一头奶牛食用.第\(i\) 份牧草的价格为\(P_i ...

  2. (转载) TextView使用一些小技巧

    TextView使用一些小技巧 标签: textviewandroid开发 2015-10-09 16:13 810人阅读 评论(0) 收藏 举报  分类: Android(20)  本文主要讲一些T ...

  3. C++ STL next_permutation() prev_permutation(a,a+n)用法。

    int a[3] = {1,2,3}; a可能形成的集合为{1,2,3},{1,3,2},{2,1,3},{2,3,1},{3,1,2},{3,2,1}. {2,1,3}的prev是{1,3,2}, ...

  4. 《鸟哥的Linux私房菜》笔记——02. 关于Linux

    Unix 历史 1969年以前:伟大的梦想--Bell, MIT 与 GE 的「Multics」系统 1969年:Ken Thompson 的小型 file server system 1973年:U ...

  5. 模板层 Template

    每一个 Web 框架都需要一种很便利的方法用于动态生成 HTML 页面. 最常见的做法是使用模板. 模板包含所需 HTML 页面的静态部分,以及一些特殊的模版语法,用于将动态内容插入静态部分. 说白了 ...

  6. linux下mysql 查看默认端口号与修改端口号方法

    一.查看默认端口号 1.登录mysql [root@localhost ~]# mysql -uroot -pEnter password: 输入数据库密码: 2.使用show global vari ...

  7. perl脚本去除文件中重复数据

    今天第一天写博客,写的不好请大家多多指教,废话不多说了,干货送上: ############################################################# #!/u ...

  8. angular7升级到angular8

    1.首先我们对:angular的命令的安装 ng install -g @angular/cli的安装则会升级到最新的版本,并且再次创建项目的时候,我们就能够使用ng version查看到已经是最新的 ...

  9. HDU-1043 Eight八数码 搜索问题(bfs+hash 打表 IDA* 等)

    题目链接 https://vjudge.net/problem/HDU-1043 经典的八数码问题,学过算法的老哥都会拿它练搜索 题意: 给出每行一组的数据,每组数据代表3*3的八数码表,要求程序复原 ...

  10. Javascript系列——对象元素的数组去重实现

    概要 这是一篇记录文,记录数组操作对象去重的实现. 需求 有这样一个数组 [{ _id: 123, name: '张三' },{ _id: 124, name: '李四' },{ _id: 123, ...