【BZOJ3110】【整体二分+树状数组区间修改/线段树】K大数查询
Description
有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
1 1 2 1
1 1 2 2
2 1 1 2
2 1 1 1
2 1 2 3
Sample Output
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操作中abs(c)<=Maxlongint
Source
【分析】
我可以吐槽一下数据很水吗?1A了
表示整体二分大法好,离线第K大都不怕。
区间修改用线段树和树状数组都可以水。
/*
明代杨慎
《临江仙·滚滚长江东逝水》 滚滚长江东逝水,浪花淘尽英雄。
是非成败转头空。
青山依旧在,几度夕阳红。
白发渔樵江渚上,惯看秋月春风。
一壶浊酒喜相逢。
古今多少事,都付笑谈中。
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <utility>
#include <iomanip>
#include <string>
#include <cmath>
#include <queue>
#include <assert.h>
#include <map>
#include <ctime>
#include <cstdlib>
#include <stack>
#define LOCAL
const int INF = 0x7fffffff;
const int MAXN = + ;
using namespace std;
//整体二分+树状数组的区间修改!
struct QUESTION{
int l, r;
int k, s, cur, type;
}q[MAXN];
int id[MAXN];
int Max, Min, n, m, Ans[MAXN];
int c[][MAXN];//0是普通和,1是全部和
int tmp[MAXN], q1[MAXN], q2[MAXN], cnt; int lowbit(int x) {return x & -x;}
int sum(int k, int x){
int cnt = ;
while (x > ){
cnt += c[k][x];
x -= lowbit(x);
}
return cnt;
}
void add(int k, int x, int val){
while (x <= n){
c[k][x] += val;
x += lowbit(x);
}
return;
}
//得到一个点真实的前缀和
int get(int x){
if (x == )
printf("");
return sum(, x) - sum(, x) * (n - x);
}
//整体二分
void solve(int l, int r, int L, int R){
if (l > r || L == R) return; int mid = (L + R) >> ;
for (int i = l; i <= r; i++){
//区间加
if (q[id[i]].type == && q[id[i]].k >= mid){//注意是区间第k大
int a = q[id[i]].l, b = q[id[i]].r;
add(, a, );
add(, b + , -);
add(, a, n - a + );
add(, b + , - (n - (b + ) + ));
}else if (q[id[i]].type == ) tmp[id[i]] = get(q[id[i]].r) - get(q[id[i]].l - );
}
//清楚标记
for (int i = l; i <= r; i++){
if (q[id[i]].type == && q[id[i]].k >= mid){
int a = q[id[i]].l, b = q[id[i]].r;
add(, a, -);
add(, b + , );
add(, a, -(n - a + ));
add(, b + , (n - (b + ) + ));
}
}
int l1 = , l2 = ;
//q1放右边,q2放左边
for (int i = l; i <= r; i++){
if (q[id[i]].type == ){
//这个要放在右边
if (q[id[i]].cur + tmp[id[i]] > q[id[i]].k - ){
q1[++l1] = id[i];
Ans[q[id[i]].s] = mid;
}else{
q[id[i]].cur += tmp[id[i]];
q2[++l2] = id[i];
}
}else{
if (q[id[i]].k >= mid) q1[++l1] = id[i];
else q2[++l2] = id[i];
}
} for (int i = ; i <= l2; i++) id[i + l - ] = q2[i];
for (int i = ; i <= l1; i++) id[i + l2 + l - ] = q1[i];
solve(l, l + l2 - , L, mid);
solve(l + l2, r, mid + , R);
}
void init(){
memset(c, , sizeof(c));
scanf("%d%d", &n, &m);
cnt = ;//cnt用来记录询问问题个数
Min = INF, Max = -INF;
for (int i = ; i <= m; i++){
int t;
scanf("%d", &t);
if (t == ){//插入操作
int l, r, x;
scanf("%d%d%d", &l, &r, &x);
q[i].type = ;
q[i].l = l; q[i].r = r;
q[i].k = x; q[i].s = ;
q[i].cur = ;
Max = max(Max, x);
Min = min(Min, x);
}else if (t == ){//询问操作
int l, r, x;
scanf("%d%d%d", &l, &r, &x);
q[i].type = ;
q[i].l = l; q[i].r = r;
q[i].k = x; q[i].cur = ;
q[i].s = ++cnt;//注意这里x是第k大
}
}
for (int i = ; i <= m; i++) id[i] = i;
//printf("%d %d\n", Max, Min);
} int main(){
int T; init();
solve(, m, Min, Max + );
for (int i = ; i <= cnt; i++) printf("%d\n", Ans[i]);
return ;
}
【BZOJ3110】【整体二分+树状数组区间修改/线段树】K大数查询的更多相关文章
- 【bzoj3110】[Zjoi2013]K大数查询 整体二分+树状数组区间修改
题目描述 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c.如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数 ...
- 【bzoj5173】[Jsoi2014]矩形并 扫描线+二维树状数组区间修改区间查询
题目描述 JYY有N个平面坐标系中的矩形.每一个矩形的底边都平行于X轴,侧边平行于Y轴.第i个矩形的左下角坐标为(Xi,Yi),底边长为Ai,侧边长为Bi.现在JYY打算从这N个矩形中,随机选出两个不 ...
- 【bzoj3132】上帝造题的七分钟 二维树状数组区间修改区间查询
题目描述 “第一分钟,X说,要有矩阵,于是便有了一个里面写满了0的n×m矩阵. 第二分钟,L说,要能修改,于是便有了将左上角为(a,b),右下角为(c,d)的一个矩形区域内的全部数字加上一个值的操作. ...
- 【bzoj4540】[Hnoi2016]序列 单调栈+离线+扫描线+树状数组区间修改区间查询
题目描述 给出一个序列,多次询问一个区间的所有子区间最小值之和. 输入 输入文件的第一行包含两个整数n和q,分别代表序列长度和询问数.接下来一行,包含n个整数,以空格隔开,第i个整数为ai,即序列第i ...
- 【bzoj3779】重组病毒 LCT+树上倍增+DFS序+树状数组区间修改区间查询
题目描述 给出一棵n个节点的树,每一个节点开始有一个互不相同的颜色,初始根节点为1. 定义一次感染为:将指定的一个节点到根的链上的所有节点染成一种新的颜色,代价为这条链上不同颜色的数目. 现有m次操作 ...
- 【树状数组区间修改区间求和】codevs 1082 线段树练习 3
http://codevs.cn/problem/1082/ [AC] #include<bits/stdc++.h> using namespace std; typedef long ...
- 【POJ3468】【树状数组区间修改】A Simple Problem with Integers
Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. On ...
- BZOJ 3110([Zjoi2013]K大数查询-区间第k大[段修改,在线]-树状数组套函数式线段树)
3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MB Submit: 418 Solved: 235 [ Submit][ ...
- 1082 线段树练习 3 && 树状数组区间修改区间查询
1082 线段树练习 3 题意: 给定序列初值, 要求支持区间修改, 区间查询 Solution 用树状数组, 代码量小, 空间占用小 巧用增量数组, 修改时在 \(l\) 处 $ + val$ , ...
随机推荐
- Delphi安装/卸载OCX控件的方法
delphi 安装卸载ocx 请参见 如下 http://blog.csdn.net/xt_chaoji/article/details/7027298 打开Delphi,关闭所有项目. 1. ...
- poj 1080 dp如同LCS问题
题目链接:http://poj.org/problem?id=1080 #include<cstdio> #include<cstring> #include<algor ...
- 让x86的android模拟器能模拟arm架构系统
网上介绍共计三种模拟器比较常用,分别是bluestacks.andy和Genymotion,前者支持ARM架构,中者支持远程控制,后者启动速度快,各有优缺点. 如果要用genymotion模拟arm的 ...
- 贵价的高级衣物清理法小Tipp之观察别人当然要从脚看起咯!
贵价的高级衣物清理法小Tipp之观察别人当然要从脚看起咯! 贵价的高级衣物清理法小Tipp之观察别人当然要从脚看起咯!
- 钥匙计数之一 - HDU 1438(状态压缩打表)
分析:首先想到每个钥匙的结尾有4种状态,不过题目还需要判断有三种不同的钥匙深度,所以每种深度结尾后有2^4种状态,0000->1111,不过题目还需需要有相邻的钥匙深度大于等于3,所以需要两种不 ...
- Spring 的注册与注入
之前和同学老是爱混淆注册与注入.今天再看一遍感觉多了一些理解. 注册就是声明bean.就是让spring能够找到这个bean服务. 注入就是把bean(A)加入到另一个bean(B)的属性中.让另外一 ...
- SQL数据类型介绍
在计算机中数据有两种特征:类型和长度.所谓数据类型就是以数据的表现方式和存储方式来划分的数据的种类. 在SQL Server 中每个变量.参数.表达式等都有数据类型.系统提供的数据类型分为几大类 ...
- Away3D ATFTexture
之前在项目中贴图大量使用了 PNG 和 jpg 遇到了个问题.在使用BitmapTexture的时候发现 是必须MIP 不管你 是否开启或者关闭 MIP 他都会去创建.而每次MIP都会根据贴图大小去生 ...
- jquery 手机 图片切换 例子 网址
http://m.swdhy.com/page/ShowCompany.aspx?cid=388481&name=山东潍坊金城服装有限公司
- springframework hibernate Transaction not successfully started
先贴出错误:org.springframework.transaction.TransactionSystemException: Could not commit Hibernate transac ...