题目描述

有N个位置,M个操作。操作有两种,每次操作如果是:

  • 1 a b c:表示在第a个位置到第b个位置,每个位置加上一个数c
  • 2 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大数查询——整体二分的更多相关文章

  1. P3332 [ZJOI2013]K大数查询 整体二分

    终于入门整体二分了,勉勉强强算是搞懂了一个题目吧. 整体二分很多时候可以比较好的离线处理区间\(K\)大值的相关问题.考虑算法流程: 操作队列\(arr\),其中有询问和修改两类操作. 每次在答案的可 ...

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

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

  3. BZOJ3110:[ZJOI2013]K大数查询(整体二分)

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

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

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

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

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

  6. 【bzoj3110】[Zjoi2013]K大数查询 整体二分+树状数组区间修改

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

  7. BZOJ3110:[ZJOI2013]K大数查询(整体二分版)

    浅谈离线分治算法:https://www.cnblogs.com/AKMer/p/10415556.html 题目传送门:https://lydsy.com/JudgeOnline/problem.p ...

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

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

  9. 【BZOJ-3110】K大数查询 整体二分 + 线段树

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

随机推荐

  1. 02-20 kd树(鸢尾花分类)

    [TOC] 更新.更全的<机器学习>的更新网站,更有python.go.数据结构与算法.爬虫.人工智能教学等着你:https://www.cnblogs.com/nickchen121/ ...

  2. Linux内存描述之高端内存–Linux内存管理(五)

    服务器体系与共享存储器架构 日期 内核版本 架构 作者 GitHub CSDN 2016-06-14 Linux-4.7 X86 & arm gatieme LinuxDeviceDriver ...

  3. JZOJ10004 列车调度

    [JZOJ100041]列车调度 Description Input Output Sample Input Sample1: 3 1 2 3 Sample2: 9 1 3 2 4 8 6 9 5 7 ...

  4. m*n 矩阵中求正方形个数

    <?php /** * Notes: * User: liubing17 * DateTime: 2019-10-17 17:10 */ function get($m, $n){ /* * 获 ...

  5. go语言正则表达式

    我们前两节课爬取珍爱网的时候,用到了很多正则表达式去匹配城市列表.城市.用户信息,其实除了正则表达式去匹配,还可以利用goquery和xpath第三方库匹配有用信息.而我利用了更优雅的正则表达式匹配. ...

  6. .netCore+Vue 搭建的简捷开发框架--目录

    .netCore+Vue 搭建的简捷开发框架 .netCore+Vue 搭建的简捷开发框架 (2)--仓储层实现和EFCore 的使用 .netCore+Vue 搭建的简捷开发框架 (3)-- Ser ...

  7. Python数据分析入门与实践 ✌✌

    Python数据分析入门与实践 (一个人学习或许会很枯燥,但是寻找更多志同道合的朋友一起,学习将会变得更加有意义✌✌) 这是一个数据驱动的时代,想要从事机器学习.人工智能.数据挖掘等前沿技术,都离不开 ...

  8. 一个“Hello World”理解JVM运行时数据区

    先上一张JVM体系结构图: 1)运行时数据区:经过编译生成的字节码文件(class文件),由class loader(类加载子系统)加载后交给执行引擎执行.在执行引擎执行的过程中产生的数据会存储在一块 ...

  9. Flask中的渲染变量

    Flask中的渲染变量 一.渲染变量 <!DOCTYPE html> <html lang="en"> <head> <meta char ...

  10. Nmon安装

    下载对应系统的nomn工具(我用centos6.5_64位下载的是nmon_linux_14i.tar.gz) mkdir /nmon cd /nmon 导入nmon的tar.gz包解压 tar -z ...