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][ ...
随机推荐
- App.config配置详解
经上一篇文章https://www.cnblogs.com/luna-hehe/p/9104701.html发现自己对配置文件很是不了解,同样还是查了半天终于发现另一片宝贵文档https://www. ...
- (转载) TextView使用一些小技巧
TextView使用一些小技巧 标签: textviewandroid开发 2015-10-09 16:13 810人阅读 评论(0) 收藏 举报 分类: Android(20) 本文主要讲一些T ...
- Android 设计一个菱形形状的Imageview组件.
网上没有资料,特来请教下大神 Android 设计一个菱形形状的Imageview组件. >> android这个答案描述的挺清楚的:http://www.goodpm.net/postr ...
- SQL 中多个 and or 的组合运算
sql关系型运算符优先级高到低为:not >and> or AND.OR运算符的组合使用 在WHERE子句中,通过AND.OR运算符可以同时连接多个条件,当然AND.OR运算符也可以同时使 ...
- NetworkX-根据权重画图
load_data = sio.loadmat(load_path) #阈值处理 mat=np.array(load_data['R']) mat[mat<0]=0 mat[mat<0.4 ...
- Python读取Matlab的.mat文件
参考网站: https://blog.csdn.net/rumswell/article/details/8545087 数据: R 22*22 double 部分截图如下: 使用sicpy.io即可 ...
- ueditor 编辑器,自定义图片上传
<div> <h1>完整demo</h1> <form method="post" name="form"> & ...
- 强化学习(2)----Q-learning
1.Q-learning主要是Q表: 当前状态s1,接下来可以有两个动作选择,看电视a1和学习a2,对于agent人来说,可以根据reward来作出决策(Policy).目的就是得到奖励最大. Q-l ...
- react-native之文件上传下载
目录 文件上传 1.文件选择 2.文件上传 1.FormData对象包装 2.上传示例 文件下载 最近react-native项目上需要做文件上传下载的功能,由于才接触react-native不久,好 ...
- [APIO2014]回文串(回文自动机)
题意 给你一个由小写拉丁字母组成的字符串 s.我们定义 s 的一个子串的存在值为这个子串在 s 中出现的次数乘以这个子串的长度. 对于给你的这个字符串 s,求所有回文子串中的最大存在值. |S|< ...