题目描述

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

输入输出格式

输入格式:

第一行N,M接下来M行,每行形如1 a b c或2 a b c

输出格式:

输出每个询问的结果

输入输出样例

输入样例#1: 复制

2 5
1 1 2 1
1 1 2 2
2 1 1 2
2 1 1 1
2 1 2 3
输出样例#1: 复制

1
2
1

说明

【样例说明】

第一个操作 后位置 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<=long long

题解

据说这是一道CDQ的板子题(然而为什么还有大佬说这是整体二分呢……蒟蒻实在搞不清楚有什么不同的……)

这里要二分的有两个,一个是询问,一个是答案(题目已经保证了答案都在1-n的范围内)

先二分一个答案,如果查询所得的排名小于询问(即求得的k比询问小),说明答案应该更大,放到右边递归处理,否则答案应该更小,放到左边递归(放到左边的话要记得减掉查询出来的k)

查询的话是区间修改和区间询问,用树状数组就可以了

 //minamoto
#include<iostream>
#include<cstdio>
#define ll long long
using namespace std;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[<<],*p1=buf,*p2=buf;
inline int read(){
#define num ch-'0'
char ch;bool flag=;int res;
while(!isdigit(ch=getc()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getc());res=res*+num);
(flag)&&(res=-res);
#undef num
return res;
}
char sr[<<],z[];int C=-,Z;
inline void Ot(){fwrite(sr,,C+,stdout),C=-;}
inline void print(int x){
if(C><<)Ot();if(x<)sr[++C]=,x=-x;
while(z[++Z]=x%+,x/=);
while(sr[++C]=z[Z],--Z);sr[++C]='\n';
}
const int N=;
ll c1[N],c2[N];
int ans[N],pd[N],n,m;
struct node{
int type,l,r,val,id;
node(){}
node(int type,int l,int r,int val,int id):type(type),l(l),r(r),val(val),id(id){}
}a[N],lef[N],rig[N];
inline void add(int x,ll val){
int t=x;
for(int i=x;i<=n;i+=i&(-i))
c1[i]+=val,c2[i]+=val*t;
}
inline ll sum(int x){
ll res=;
for(int i=x;i;i-=i&(-i))
res+=c1[i]*(x+)-c2[i];
return res;
}
void CDQ(int ql,int qr,int l,int r){
if(ql>qr||l>r) return;
if(l==r) {for(int i=ql;i<=qr;++i) ans[a[i].id]=l;return;}
int mid=(l+r)>>;
int nowl=,nowr=;
for(int i=ql;i<=qr;++i){
if(a[i].type&){
if(a[i].val>mid) add(a[i].l,),add(a[i].r+,-),rig[++nowr]=a[i];
else lef[++nowl]=a[i];
}
else{
ll now=sum(a[i].r)-sum(a[i].l-);
if(now>=a[i].val) rig[++nowr]=a[i];
else a[i].val-=now,lef[++nowl]=a[i];
}
}
for(int i=ql;i<=qr;++i)
if((a[i].type&)&&a[i].val>mid)
add(a[i].l,-),add(a[i].r+,);
for(int i=;i<=nowl;++i) a[ql+i-]=lef[i];
for(int i=;i<=nowr;++i) a[ql+nowl-+i]=rig[i];
CDQ(ql,ql+nowl-,l,mid);
CDQ(ql+nowl,qr,mid+,r);
}
int main(){
//freopen("testdata.in","r",stdin);
n=read(),m=read();
for(int i=;i<=m;++i){
int type=read(),l=read(),r=read(),val=read();
a[i]=node(type,l,r,val,i);
if(type&) pd[i]=;
}
CDQ(,m,,n);
for(int i=;i<=m;++i)
if(pd[i]) print(ans[i]);
Ot();
return ;
}

BZOJ 3110 [Zjoi2013]K大数查询 (CDQ分治+树状数组)的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  8. BZOJ 3110 [Zjoi2013]K大数查询(整体二分)

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 11654  Solved: 3505[Submit][St ...

  9. BZOJ 3110 [Zjoi2013]K大数查询

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

随机推荐

  1. 最值得学习阅读的10个C语言开源项目代码

    阅读优秀代码是提高开发人员修为的一种捷径-- 1. Webbench Webbench是一个在linux下使用的非常简单的网站压测工具.它使用fork()模拟多个客户端同时访问我们设定的URL,测试网 ...

  2. 归纳整理Linux下C语言常用的库函数----文件操作

    在没有IDE的时候,记住一些常用的库函数的函数名.参数.基本用法及注意事项是很有必要的. 参照Linux_C_HS.chm的目录,我大致将常用的函数分为一下几类: 1. 内存及字符串控制及操作 2. ...

  3. git 查询某人的提交记录

    git log --author=liubo --name-only

  4. dedecms分页

    mshd_orderlist.php $page = isset($_REQUEST[; $count = $mshd_miaosha_member_obj -> getMemberList(t ...

  5. 添加普通用户为sudo用户

    https://www.linuxidc.com/Linux/2017-01/139361.htm 1.打开sudoers文件 切换到root用户下,cd root,运行visudo命令,visudo ...

  6. oepnni安装

    sudo apt-get install libopenni-dev libopenni2-dev / apt-get install libqhull-dev

  7. Centos 7 手把手教你使用YUM方式安装并配置Nginx+php7-fpm+MySQL

    需要准备的内容 一台纯净系统的服务器 远程连接服务器的工具 (我这里使用Xshell) 安装nginx 链接上服务器后执行 yum install nginx  这里需要输入y 后回车,开始安装ngi ...

  8. Hbase和传统数据库的区别

    在说HBase之前,我想再唠叨几句.做互联网应用的哥们儿应该都清楚,互联网应用这东西,你没办法预测你的系统什么时候会被多少人访问,你面临的用户到底有多少,说不定今天你的用户还少,明天系统用户就变多了, ...

  9. linux 搭建php网站许愿墙

    网站素材在:https://i.cnblogs.com/Files.aspx 首先需要搭建本地yum源,详情参考: http://www.cnblogs.com/jw35/p/5967677.html ...

  10. Oracle FND API–Create User

    --API - fnd_user_pkg.createuser----Example -- -- ---------------------------------------- API to CRE ...