[ZJOI2013]K大数查询——整体二分
题目描述
有N个位置,M个操作。操作有两种,每次操作如果是:
1 a b c
:表示在第a个位置到第b个位置,每个位置加上一个数c2 a b c
:表示询问从第a个位置到第b个位置,第C大的数是多少。
思路
比较基础的整体二分。我们二分出$mid,对于值域[l,r]对应的操作[L,R]$,若为操作1,则考虑把$val>mid$的插入线段树中,表示比$mid$大的值的个数,若为操作2,先询问$[q[i].l,q[i].r]$中比$mid$大的值的个数,然后把当前询问填到左右区间再处理。讲的很简单,调过来整体二分原理的一些东西,,,毕竟这题还是比较板子的。
code
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define I inline
#define smid (l+r>>1)
#define lch (now<<1)
#define rch (now<<1|1)
using namespace std;
const int N=;
typedef long long LL;
int n,m,tot;
LL ans[N];
struct segment
{
LL sum,pls;
}sgt[N<<];
struct node
{
int l,r,k,op,id;
}q[N<<],q1[N<<],q2[N<<]; I int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
} I LL readll()
{
LL x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
} I void pushup(int now)
{
sgt[now].sum=sgt[lch].sum+sgt[rch].sum;
} I void pushdown(int now,int l,int r)
{
if(!sgt[now].pls)return;
sgt[lch].pls+=sgt[now].pls;
sgt[rch].pls+=sgt[now].pls;
sgt[lch].sum+=(smid-l+)*sgt[now].pls;
sgt[rch].sum+=(r-smid)*sgt[now].pls;
sgt[now].pls=;
} I void modify(int now,int l,int r,int x,int y,int val)
{
if(x<=l&&r<=y)
{
sgt[now].pls+=val;
sgt[now].sum+=(r-l+)*val;
return;
}
pushdown(now,l,r);
if(x<=smid)modify(lch,l,smid,x,y,val);
if(smid<y)modify(rch,smid+,r,x,y,val);
pushup(now);
} I LL query(int now,int l,int r,int x,int y)
{
if(x<=l&&r<=y)return sgt[now].sum;
pushdown(now,l,r);
LL res=;
if(x<=smid)res+=query(lch,l,smid,x,y);
if(smid<y)res+=query(rch,smid+,r,x,y);
pushup(now);
return res;
} I void solve(int l,int r,int L,int R)
{
if(L>R)return;
if(l==r)
{
for(int i=L;i<=R;i++)if(q[i].op==)ans[q[i].id]=l;
return;
}
int mid=(l+r>>),cnt1=,cnt2=;
for(int i=L;i<=R;i++)
{
if(q[i].op==)
{
if(q[i].k>mid)
modify(,,n,q[i].l,q[i].r,),q2[++cnt2]=q[i];
else q1[++cnt1]=q[i];
}
else
{
LL tmp=query(,,n,q[i].l,q[i].r);
if(q[i].k>tmp)q[i].k-=tmp,q1[++cnt1]=q[i];
else q2[++cnt2]=q[i];
}
}
for(int i=;i<=cnt2;i++)if(q2[i].op==)modify(,,n,q2[i].l,q2[i].r,-);
for(int i=;i<=cnt1;i++)q[L+i-]=q1[i];
for(int i=;i<=cnt2;i++)q[L+cnt1+i-]=q2[i];
solve(l,mid,L,L+cnt1-);solve(mid+,r,L+cnt1,R);
} int main()
{
n=read();m=read();
for(int i=;i<=m;i++)
{
q[i].op=read();q[i].l=read();q[i].r=read();q[i].k=readll();
if(q[i].op==)q[i].id=++tot;
}
solve(-n,n,,m);
for(int i=;i<=tot;i++)printf("%lld\n",ans[i]);
}
[ZJOI2013]K大数查询——整体二分的更多相关文章
- P3332 [ZJOI2013]K大数查询 整体二分
终于入门整体二分了,勉勉强强算是搞懂了一个题目吧. 整体二分很多时候可以比较好的离线处理区间\(K\)大值的相关问题.考虑算法流程: 操作队列\(arr\),其中有询问和修改两类操作. 每次在答案的可 ...
- BZOJ 3110: [Zjoi2013]K大数查询 [整体二分]
有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少. N ...
- BZOJ3110:[ZJOI2013]K大数查询(整体二分)
Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c.如果是2 a b c形式,表示询问从第a个位置到第b个位 ...
- BZOJ.3110.[ZJOI2013]K大数查询(整体二分 树状数组/线段树)
题目链接 BZOJ 洛谷 整体二分求的是第K小(利用树状数组).求第K大可以转为求第\(n-K+1\)小,但是这样好像得求一个\(n\). 注意到所有数的绝对值\(\leq N\),将所有数的大小关系 ...
- BZOJ 3110 [Zjoi2013]K大数查询 ——整体二分
[题目分析] 整体二分显而易见. 自己YY了一下用树状数组区间修改,区间查询的操作. 又因为一个字母调了一下午. 貌似树状数组并不需要清空,可以用一个指针来维护,可以少一个log 懒得写了. [代码] ...
- 【bzoj3110】[Zjoi2013]K大数查询 整体二分+树状数组区间修改
题目描述 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c.如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数 ...
- BZOJ3110:[ZJOI2013]K大数查询(整体二分版)
浅谈离线分治算法:https://www.cnblogs.com/AKMer/p/10415556.html 题目传送门:https://lydsy.com/JudgeOnline/problem.p ...
- BZOJ 3110 [ZJOI2013]K大数查询 (整体二分+线段树)
和dynamic rankings这道题的思想一样 只不过是把树状数组换成线段树区间修改,求第$K$大的而不是第$K$小的 这道题还有负数,需要离散 #include <vector> # ...
- 【BZOJ-3110】K大数查询 整体二分 + 线段树
3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 6265 Solved: 2060[Submit][Sta ...
随机推荐
- linux登录后出现-bash-4.1$
linux登录后有时候会出现-bash-4.1$ 造成这样的原因: 与这个用户有关环境变量没了,有关的文件被删除.也就是用户的家目录下面 .bash_profile .bashrc 被删除. 解决办法 ...
- Mysql Hash索引和B-Tree索引区别(Comparison of B-Tree and Hash Indexes)
上篇文章中说道,Mysql中的Btree索引和Hash索引的区别,没做展开描述,今天有空,上Mysql官方文档找到了相关答案,看完之后,针对两者的区别做如下总结: 引用维基百科上的描述,来解释一下这两 ...
- spring5 源码深度解析----- 事务增强器(100%理解事务)
上一篇文章我们讲解了事务的Advisor是如何注册进Spring容器的,也讲解了Spring是如何将有配置事务的类配置上事务的,实际上也就是用了AOP那一套,也讲解了Advisor,pointcut验 ...
- 解决window.onload延迟加载问题
window.onload方法,表示当页面所有的元素都加载完毕,并且所有要请求的资源也加载完毕才触发执行function这个匿名函数里边的具体内容.这样肯定保证了代码在domReady之后执行.使用w ...
- CH3803扑克牌
Description 背景 lqhsr生日那天,Rainbow来找lqhsr玩扑克牌-- 玩着玩着Rainbow觉得太没意思了,于是决定给lqhsr一个考验~~~ 描述 Rainbow把一副扑克牌( ...
- 「3D建模」ZBrush如何雕刻头部
加载项目开始 1. 如果未显示灯箱,请按逗号(,)或灯箱按钮. 2. 单击项目选项卡,然后双击DefaultSphere项目.它将被加载到ZBrush中. 3. 在工具>几何子选项板中,将SDi ...
- 关于用gulp合并压缩seaJs模块
现在很多人都在用seaJs来开发项目,seaJs上手容易,操作简单.但在后期做合并压缩的时候却中了个巨大无比的坑,但坑也总得有人来填.于是花了将近一个星期的时间来填了这坑,现将填坑的一些心得与大家分享 ...
- 小白学 Python(5):基础运算符(上)
人生苦短,我选Python 前文传送门 小白学 Python(1):开篇 小白学 Python(2):基础数据类型(上) 小白学 Python(3):基础数据类型(下) 小白学 Python(4):变 ...
- Linux的一些常用命令(一)
linux 快捷键1.ls 列出本地址上文件, -a 列出所有(包括隐藏文件) -l 按照列表方式显示 -t 按照时间方式排序 2.touch 创建文件 3. echo 'abc' > 文件名 ...
- Pathon中numpy模块
目录 numpy模块 切割矩阵 矩阵元素替换 矩阵的合并 通过函数创建矩阵 fromstring/fromfunctions 矩阵的运算 常用矩阵运函数 矩阵的点乘 矩阵的逆 矩阵的其他操作 nump ...