[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 ...
随机推荐
- 如何选择一款适合自己操作系统、Windows、Mac还是Linux?
如何选择一款适合自己操作系统.Windows.Mac还是Linux? 作者:我们都很努力着 简介:电脑已经逐渐离不开我们生活,但是如何选择一个我们最佳,最适合的电脑操作系统就成了一些困难选择人士的一个 ...
- Django与drf 源码视图解析
0902自我总结 Django 与drf 源码视图解析 一.原生Django CBV 源码分析:View """ 1)as_view()是入口,得到view函数地址 2) ...
- 线程封闭之栈封闭和ThreadLocal
线程封闭 在多线程的环境中,我们经常使用锁来保证线程的安全,但是对于每个线程都要用的资源使用锁的话那么程序执行的效率就会受到影响,这个时候可以把这些资源变成线程封闭的形式. 1.栈封闭 所谓的栈封闭其 ...
- Tomcat 的单机多实例配置
有时候需要在一个服务器上部署多个Tomcat,通过不同的端口进行区分,比如,反向代理.但是不想简单的通过复制Tomcat来实现,这样既不方便以后的升级也不方便管理,那么这时候就需要配置Tomcat的单 ...
- springMVC初学简单例子
新建web项目,保留web.xml. 配置web.xml文件(/WEB-INF/下): <?xml version="1.0" encoding="UTF-8&qu ...
- angular7新特性
Angular 是最流行的 Web 应用程序开发框架之一.随着 Angular 7 的发布,它为 Web 开发人员带来了更多功能,包括核心框架.Angular Material.与主要版本保持同步的 ...
- Markdown进阶(1)
对于工科生来说,在书写Markdown文本时,免不了要和上下标打交道,网上的博客大多良莠不齐,不太友好,本文想尽可能地解决一些在看完基础教程后再来书写Markdown文本时容易遇到的问题. 1.上下标 ...
- 用最复杂的方式学会数组(Python实现动态数组)
Python序列类型 在本博客中,我们将学习探讨Python的各种"序列"类,内置的三大常用数据结构--列表类(list).元组类(tuple)和字符串类(str). 不知道你发现 ...
- Java多线程编程(七)线程状态、线程组与异常处理
一.线程的状态 线程对象在不同的运行时期有不同的状态,状态信息就存在于State枚举类中. 调用与线程有关的方法后,会进入不同的线程状态,这些状态之间某些是可双向切换的,比如WAITING和RUNNI ...
- split分割文件与数据
split主要用途:在之前计算机发展的时候,我们必须分割文件,才能将大量数据放入多张软盘中,而今我们分割文件有了其他的目的,比如提高可读性,生成日志以及发送有大小限制的E-mail附件. 工作原理:s ...