K大数查询

【问题描述】

有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

【输出格式】

输出每个询问的结果

【样例输入】

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

【样例输出】

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<=Maxlongint


题解:

我们将询问离线,做整体二分

题目中有负数,那么我们转化一下,将每个数变为n-i+1,输出答案时再变为n-ans+1

对于一个操作1,如果这个操作加入的c是不超过mid的

用线段树在区间内加1,表示此区间小于等于mid的数多了一个,那么将它放置到左区间

否则将其放置到右区间,表示这个操作的贡献在右区间

对于一个操作2,查询在区间内小于等于mid的数的个数tot

如果tot超过k,将其放置到左区间,表示答案在左区间

否则将k减去tot,放置到右区间,表示需要在右区间找k-tot大的数

 #include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
struct S { long long x, y, z, id, flag; } a[], c[];
bool lr[];
long long n, m, tot, maxx = -;
long long sum[], ans[], node[];
void Down(long long k, int l, int r)
{
if(node[k] != )
{
int mi = (l + r) >> ;
node[k * ] += node[k];
node[k * + ] += node[k];
sum[k * ] += node[k] * (mi - l + );
sum[k * + ] += node[k] * (r - mi);
node[k] = ;
}
}
void Inc(int k, int l, int r, int x, int y, int z)
{
if(x <= l && r <= y)
{
sum[k] += z * (r - l + );
node[k] += z;
return;
}
Down(k, l, r);
int mi = (l + r) >> ;
if(mi >= x) Inc(k * , l, mi, x, y, z);
if(mi < y) Inc(k * + , mi + , r, x, y, z);
sum[k] = sum[k * ] + sum[k * + ];
}
long long Sum(long long k, long long l, long long r, long long x, long long y)
{
if(x <= l && r <= y) return sum[k];
Down(k, l, r);
long long mi = (l + r) >> , res = ;
if(mi >= x) res += Sum(k * , l, mi, x, y);
if(mi < y) res += Sum(k * + , mi + , r, x, y);
return res;
}
void Two(long long x, long long y, long long l, long long r)
{
cout<<x<<' '<<y<<' '<<l<<' '<<r<<endl;
long long mi = (l + r) >> ;
if(l == r)
{
for(int i = x; i <= y; ++i)
if(a[i].flag)
ans[a[i].id] = mi;
return;
}
long long temp, s = x;
for(int i = x; i <= y; ++i)
{
if(a[i].flag)
{
temp = Sum(, , * n + , a[i].x, a[i].y);
if(temp < a[i].z)
{
a[i].z -= temp;
lr[i] = false;
}
else
{
++s;
lr[i] = true;
}
}
else
{
if(a[i].z <= mi)
{
Inc(, , * n + , a[i].x, a[i].y, );
++s;
lr[i] = true;
}
else lr[i] = false;
}
}
for(int i = x; i <= y; ++i)
if(!a[i].flag && a[i].z <= mi)
Inc(, , * n + , a[i].x, a[i].y, -);
long long o = x;
for(int i = x; i <= y; ++i)
if(lr[i]) c[o++] = a[i];
else c[s++] = a[i];
for(int i = x; i <= y; ++i) a[i] = c[i];
Two(x, o - , l, mi), Two(o, y, mi + , r);
}
int main()
{
scanf("%lld%lld", &n, &m);
for(int i = ; i <= m; ++i)
{
scanf("%lld%lld%lld%lld", &a[i].flag, &a[i].x, &a[i].y, &a[i].z);
--a[i].flag;
if(!a[i].flag)
{
a[i].z = n - a[i].z + ;
maxx = (a[i].z > maxx) ? a[i].z : maxx;
}
else a[i].id = ++tot;
}
Two(, m, , maxx);
for(int i = ; i <= tot; ++i) printf("%lld\n", n - ans[i] + );
}

K大数查询 BZOJ 3110的更多相关文章

  1. 【ZJOI2013】k大数查询 BZOJ 3110

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

  2. BZOJ 3110 K大数查询 | 整体二分

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

  3. [BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树)

    [BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树) 题面 原题面有点歧义,不过从样例可以看出来真正的意思 有n个位置,每个位置可以看做一个集合. ...

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. HDU 6166 Senior Pan(多校第九场 二进制分组最短路)

    题意:给出n个点和m条有向边(有向边!!!!我还以为是无向查了半天),然后给出K个点,问这k个点中最近的两点的距离 思路:比赛时以为有询问,就直接丢了,然后这题感觉思路很棒,加入把所有点分成起点和终点 ...

  2. Robot Framework(十) 执行测试用例——测试执行

    3.2测试执行 本节描述如何执行从解析的测试数据创建的测试套件结构,如何在失败后继续执行测试用例,以及如何正常停止整个测试执行. 3.2.1执行流程 执行套房和测试 设置和拆卸 执行顺序 3.2.2继 ...

  3. bootstrap 按钮组的嵌套

    您可以在一个按钮组内嵌套另一个按钮组,即,在一个 .btn-group 内嵌套另一个 .btn-group .当您想让下拉菜单与一系列按钮组合使用时,就会用到这个. 实例: <!DOCTYPE ...

  4. mysql 复制中的 paxso 的两阶段和事务两阶段的区别

    1.普通的两阶段是 推送不同的数据给不同的主机,一旦出现网络中断,造成问题是不可服务. 因为本身有锁,故无所谓. 2.paxos 的两阶段是将相同的 数据给不同的主机,一旦超过半数即可认为成功.

  5. apache 报413

    http://www.hostlift.com/apache/modsecurity-request-body-content-length-is-larger-than-the-configured ...

  6. centos7 samba配置完成后不管怎么登陆都会显示密码错误的解决方案

    添加系统用户 useradd samba 添加samba用户 smbpasswd -a samba 激活samba用户 smbpasswd -e samba 1.win+r运行secpol.msc打开 ...

  7. [LUOGU] P4767 [IOI2000]邮局

    https://www.luogu.org/problemnew/show/P4767 四边形不等式好题! 可以设f[i][j]表示前i个村庄,建了j个邮局的最小代价. 转移:f[i][j]=min{ ...

  8. nginx目录结构和配置文件

    nginx软件功能模块说明 Nginx软件之所以强大,是因为它具有众多的功能模块,下面列出了企业常用的重要模块. (1) Nginx核心功能模块(Core functionality)nginx核心功 ...

  9. python基础学习笔记——time模块

    time模块 time翻译过来就是时间,有我们其实在之前编程的时候有用到过. #常用方法 1.time.sleep(secs) (线程)推迟指定的时间运行.单位为秒. 2.time.time() 获取 ...

  10. C#学习基础概念二十五问

    C#学习基础概念二十五问 1.静态变量和非静态变量的区别?2.const 和 static readonly 区别?3.extern 是什么意思?4.abstract 是什么意思?5.internal ...