3110 [Zjoi2013]K大数查询

有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

2 5
1 1 2 1
1 1 2 2
2 1 1 2
2 1 1 1
2 1 2 3

Sample Output

1
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

题解:


题意概括

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

N,M<=50000
a<=b<=N
1操作中abs(c)<=N
2操作中c<=Maxlongint


题解

  让我们来考虑神奇的分治算法。

  整体二分!!(当你会了)

  首先当你已经掌握了树状数组的区间加和区间询问(如果不会->点这里

  我们考虑二分答案。

  注意进行以下操作要严格按照输入时间先后顺序来。

  首先对于加进去的数字c,我们把他变成n-c+1,这样就把询问前k大变成了前k小。

  如果是修改操作,如果修改的值比当前的mid值小,就修改,并扔到左区间里面。否则扔到右边。

  如果是询问操作,如果在当前的状态下,该询问的区间内查询到的数的个数res比当前询问的c要大(或者相等),那么显然答案在左区间,把他扔到左边,否则把他的c减掉res再扔到右边去。

  然后递归分治两个区间就可以了。

  (本质是个二分答案的升级版)

  

参考代码:

 /**************************************************************
Problem: 3110
User: SongHL
Language: C++
Result: Accepted
Time:1880 ms
Memory:3640 kb
****************************************************************/ #include<bits/stdc++.h>
using namespace std;
#define lowbit(x) x&-x
#define clr(a,b) memset(a,b,sizeof a)
typedef long long ll;
const int maxn=;
int n,m,id[maxn],templ[maxn],tempr[maxn];
ll tree[][maxn];
inline 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;
}
inline void add(int t,int x,int y)//单点加
{
while(x<=n+)
{
tree[t][x]+=y;
x+=lowbit(x);
}
}
inline void update(int l,int r,int val)//区间加
{
add(,l,val);add(,l,l*val);
add(,r+,-val);add(,r+,-val*(r+));
}
inline ll Sum(int t,int x)//前缀和
{
ll ans=;
while(x>)
{
ans+=tree[t][x];
x-=lowbit(x);
}
return ans;
}
inline ll query(int l,int r)//区间求和
{
return Sum(,r)*(r+)-Sum(,l)*l-Sum(,r)+Sum(,l);
}
struct Node{
int type,l,r,x,ans;
void Get()
{
type=read();l=read();r=read();x=read();
if(type==) x=n-x+;
}
} a[maxn]; inline void Solve(int lx,int rx,int l,int r)
{
if(l>r) return ;
if(lx==rx)
{
for(int i=l;i<=r;++i) a[id[i]].ans=lx;
return ;
}
int midx=lx+rx>>;
int L=,R=;
for(int i=l;i<=r;++i)
{
if(a[id[i]].type==)
{
if(a[id[i]].x<=midx) templ[++L]=id[i],update(a[id[i]].l,a[id[i]].r,);
else tempr[++R]=id[i];
}
else
{
ll res=query(a[id[i]].l,a[id[i]].r);
if(res>=a[id[i]].x) templ[++L]=id[i];
else tempr[++R]=id[i],a[id[i]].x-=res;
}
}
for(int i=;i<=L;++i)
{
if(a[templ[i]].type==)
update(a[templ[i]].l,a[templ[i]].r,-);
} for(int i=l;i<=l+L-;++i) id[i]=templ[i-(l-)];
for(int i=r-R+;i<=r;++i) id[i]=tempr[i-(r-R)]; Solve(lx,midx,l,l+L-);
Solve(midx+,rx,r-R+,r);
} int main()
{
n=read();m=read();
for(int i=;i<=m;++i) a[i].Get(),id[i]=i;
clr(tree,);
Solve(,*n+,,m);
for(int i=;i<=m;++i)
if(a[i].type==) printf("%d\n",n-a[i].ans+);
return ;
}

  

BZOJ3110[Zjoi2013]K大数查询(树状数组+整体二分)的更多相关文章

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

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

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

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

  3. BZOJ3110 [Zjoi2013]K大数查询 树套树 线段树 整体二分 树状数组

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3110 题意概括 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位 ...

  4. [BZOJ3110] [Zjoi2013] K大数查询 (树套树)

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

  5. Cogs 1345. [ZJOI2013] K大数查询(树套树)

    [ZJOI2013] K大数查询 /* 树套树写法. bzoj过不了. 可能有负数要离散吧. 线段树套线段树. 外层权值线段树,内层区间线段树维护标记. 对权值建一棵权值线段树. 某个点表示权值在某个 ...

  6. 【BZOJ3110】[Zjoi2013]K大数查询 树套树

    [BZOJ3110][Zjoi2013]K大数查询 Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c,如果 ...

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

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

  8. BZOJ3110: [Zjoi2013]K大数查询

    喜闻乐见的简单树套树= =第一维按权值建树状数组,第二维按下标建动态开点线段树,修改相当于第二维区间加,查询在树状数组上二分,比一般的线段树还短= =可惜并不能跑过整体二分= =另外bzoj上的数据有 ...

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

    BZOJ Luogu sol 整体二分,其实很简单的啦. 对所有询问二分一个答案mid,把所有修改操作中数字大于mid的做一个区间覆盖(区间加1) 查询就是区间查询 然后左右分一分即可 注意是第k大 ...

随机推荐

  1. .NET Core 对龙芯的支持情况和对 .NET Core 开发嵌入式的思考

    目录 .NET Core 对龙芯的支持情况和对 .NET Core 开发嵌入式的思考 一,遗憾的尝试 二,.NET Core在嵌入式下的几点不足 三,.NET Core 龙芯移植的进展和资料 .NET ...

  2. HTTP的请求方式

    GET 请求获取 Request-URI 所标识的资源POST 在 Request-URI 所标识的资源后附加新的数据HEAD  请求获取由 Request-URI 所标识的资源的响应消息报头PUT ...

  3. [java] 笔记 from黑马

    1. 关于String的创建.   PS:String的底层是用字节数组来实现的. 2.字符串常量池的笔记 具体指向是如下图的, 注意看0x666和0x999这两个地址. 3.原因如下: 4. 5. ...

  4. 05-商品类别数据和VUE展示

    一.商品类别数据和VUE展示 1.商品类别数据接口 将商品类别数据展示出来,视图(views.py)代码如下: class CategoryViewset(mixins.ListModelMixin, ...

  5. (线段树)A Corrupt Mayor's Performance Art

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5023 题意: 区间更新, 区间询问: 题解: 区间更新, 区间询问, 一共30种颜色, 可用int 来 ...

  6. 快速搭建 SpringCloud 微服务开发环境的脚手架

    本文适合有 SpringBoot 和 SpringCloud 基础知识的人群,跟着本文可使用和快速搭建 SpringCloud 项目. 本文作者:HelloGitHub-秦人 HelloGitHub ...

  7. Solr搜索引擎【索引提交、事务日志、原子更新】

    一.索引提交 当一个文档被添加到Solr中,但没有提交给索引之前,这个文档是无法被搜索的.换句话说,从查询的角度看,文档直到提交之后才是可见的.Solr有两种类型的提交:软提交和正常提交[也称硬提交] ...

  8. 利用Spring AOP的通知类型以及创建通知

    写在最前端 1.SpringAOP中共有六种通知类型,只要我们自定义一个类实现对应的接口,它们全都是org.springframework.aop包中的. 2.AOP的连接点可以是方法调用.方法调用本 ...

  9. Spring Cloud Alibaba(五)RocketMQ 异步通信实现

    本文探讨如何使用 RocketMQ Binder 完成 Spring Cloud 应用消息的订阅和发布. 介绍 RocketMQ 是一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的.高 ...

  10. 【10分钟学Spring】:(一)初识Spring框架

    简介 Spring是一个轻量级的企业级的Java开发框架.主要是用来替代原来更加重量级的企业级Java技术,比如EJB(Enterprise JavaBean).Java数据对象(Java Data ...