E-Find the median_2019牛客暑期多校训练营(第七场)

题意
N次操作,每次塞入区间\([L,R]\)的每个数,并输出此时的中位数。
题解
如果题目不是每次塞入一整个区间,而是只塞入一个数,可以简单的建权值线段树查询区间第K大,由于每次都是查询整个区间就不用主席树了。
现在题目是塞一个区间,那么就要想办法把原来的权值线段树的单点更新变为区间更新,如果L,R的范围较小,可以很容易的把单点修改换成区间修改,题目范围是1e9不可能对整个1e9的区间建树,我们就需要对区间端点进行离散化,原来权值线段树的每一个点的含义由点变成了区间,例如1-5,6-10,离散化为为1-2,3-4,点1就表示1-5这个区间,点3表示6-10这个区间,
但是这样定义点的含义会有一点问题,比如1-5,5-10,离散化为1-2,2-3,此时点1表示1-5,点2表示5-10,点1和点2表示的区间重叠了,那如果我把点含义定义成左闭右开呢?点1表示1-4,点2表示5-9,点10表示10-10,此时如果我想更新1-5这个区间,会发现没法更新,这样定义也不行。
一种做法是把输入的区间右端点+1,比如上面的例子1-5,5-10,变成1-6,5-11,离散化后变成1-3,2-4,点1表示1-4,点2表示5-5,点3表示6-9,点4表示10-10,我要更新1-5只要更新点1和2就行了,问题得到解决。
代码
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
const int mx = 8e5+5;
int x[mx], y[mx];
vector <int> vv;
int getid(int x) {
return lower_bound(vv.begin(), vv.end(), x) - vv.begin() + 1;
}
struct Tree {
int lazy, len;
ll sum;
}tree[mx<<2];
void pushUp(int rt) {
tree[rt].sum = tree[rt<<1].sum + tree[rt<<1|1].sum;
}
void pushDown(int rt) {
tree[rt<<1].lazy += tree[rt].lazy;
tree[rt<<1|1].lazy += tree[rt].lazy;
tree[rt<<1].sum += 1LL * tree[rt<<1].len * tree[rt].lazy;
tree[rt<<1|1].sum += 1LL * tree[rt<<1|1].len * tree[rt].lazy;
tree[rt].lazy = 0;
}
void build(int l, int r, int rt) {
if (l == r) {
tree[rt].len = vv[r+1-1] - vv[l-1];
tree[rt].sum = tree[rt].lazy = 0;
return;
}
int mid = (l + r) / 2;
build(l, mid, rt<<1);
build(mid+1, r, rt<<1|1);
tree[rt].len = tree[rt<<1].len + tree[rt<<1|1].len;
}
void update(int L, int R, int l, int r, int rt) {
if (L <= l && r <= R) {
tree[rt].sum += tree[rt].len;
tree[rt].lazy += 1;
return;
}
int mid = (l + r) / 2;
pushDown(rt);
if (L <= mid) update(L, R, l, mid, rt<<1);
if (mid < R) update(L, R, mid+1, r, rt<<1|1);
pushUp(rt);
}
int query(int l, int r, ll k, int rt) {
if (l == r) {
ll t = tree[rt].sum / tree[rt].len;
return vv[l-1] + (k-1) / t;
}
pushDown(rt);
int mid = (l + r) / 2;
if (tree[rt<<1].sum >= k) return query(l, mid, k, rt<<1);
else return query(mid+1, r, k-tree[rt<<1].sum, rt<<1|1);
}
int main() {
ll n, A1, B1, C1, M1, A2, B2, C2, M2;
scanf("%lld", &n);
scanf("%d%d%lld%lld%lld%lld", &x[1], &x[2], &A1, &B1, &C1, &M1);
scanf("%d%d%lld%lld%lld%lld", &y[1], &y[2], &A2, &B2, &C2, &M2);
for (int i = 3; i <= n; i++) {
x[i] = (A1*x[i-1] + B1*x[i-2] + C1) % M1;
y[i] = (A2*y[i-1] + B2*y[i-2] + C2) % M2;
}
for (int i = 1; i <= n; i++) {
if (x[i] > y[i]) swap(x[i], y[i]);
x[i]++; y[i]+=2;
vv.push_back(x[i]);
vv.push_back(y[i]);
}
sort(vv.begin(), vv.end());
vv.erase(unique(vv.begin(), vv.end()), vv.end());
vv.push_back(vv[vv.size()-1]+1);
build(1, vv.size()-1, 1);
ll sum = 0;
for (int i = 1; i <= n; i++) {
update(getid(x[i]), getid(y[i])-1, 1, vv.size()-1, 1);
sum += y[i]-x[i];
printf("%d\n", query(1, vv.size()-1, (sum-1)/2+1, 1));
}
return 0;
}
E-Find the median_2019牛客暑期多校训练营(第七场)的更多相关文章
- 2019牛客暑期多校训练营(第九场)A:Power of Fibonacci(斐波拉契幂次和)
题意:求Σfi^m%p. zoj上p是1e9+7,牛客是1e9: 对于这两个,分别有不同的做法. 前者利用公式,公式里面有sqrt(5),我们只需要二次剩余求即可. 后者mod=1e9,5才 ...
- 2019牛客暑期多校训练营(第一场)A题【单调栈】(补题)
链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 题目描述 Two arrays u and v each with m distinct elem ...
- 2019牛客暑期多校训练营(第一场) B Integration (数学)
链接:https://ac.nowcoder.com/acm/contest/881/B 来源:牛客网 Integration 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 5242 ...
- 2019牛客暑期多校训练营(第一场) A Equivalent Prefixes ( st 表 + 二分+分治)
链接:https://ac.nowcoder.com/acm/contest/881/A 来源:牛客网 Equivalent Prefixes 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/ ...
- 2019牛客暑期多校训练营(第二场)F.Partition problem
链接:https://ac.nowcoder.com/acm/contest/882/F来源:牛客网 Given 2N people, you need to assign each of them ...
- 2019牛客暑期多校训练营(第一场)A Equivalent Prefixes(单调栈/二分+分治)
链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 Two arrays u and v each with m distinct elements ...
- [状态压缩,折半搜索] 2019牛客暑期多校训练营(第九场)Knapsack Cryptosystem
链接:https://ac.nowcoder.com/acm/contest/889/D来源:牛客网 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 262144K,其他语言52428 ...
- 2019牛客暑期多校训练营(第二场)J-Subarray(思维)
>传送门< 前言 这题我前前后后看了三遍,每次都是把网上相关的博客和通过代码认真看了再思考,然并卵,最后终于第三遍也就是现在终于看懂了,其实懂了之后发现其实没有那么难,但是的的确确需要思维 ...
- J-Subarray_2019牛客暑期多校训练营(第二场)
题意 有一个只由1,-1组成的数组,给出所有连续的1所在位置,求满足1的个数大于-1的个数的子区间的数量 题解 参考博客:https://www.cnblogs.com/Yinku/p/1122149 ...
随机推荐
- 模块购物商城和ATM机代码:
http://outofmemory.cn/python/video/let-us-python/ python为程序员服务 快来加入群[python爬虫交流群](群号570070796),发现精彩 ...
- c#小灶——初识c#
提到c#,就不得不说.net,.net是微软开发的一个平台,简单来说,在这个平台上,可以编写.运行程序.可能很多人觉得这个平台离我们很遥远,其实不然,这个平台就一直在我们的windows操作系统里,默 ...
- 1. 源码分析---SOFARPC可扩展的机制SPI
这几天离职在家,正好没事可以疯狂的输出一下,本来想写DUBBO的源码解析的,但是发现写DUBBO源码的太多了,所以找一个写的不那么多的框架,所以就选中SOFARPC这个框架了. SOFARPC是蚂蚁金 ...
- eclipse的下载安装配置
1.在eclipse官网下载与你电脑版本相对应的安装包.链接:https://www.eclipse.org/downloads/eclipse-packages/ 2.下载与eclipse版本相对应 ...
- Thrift框架快速入门
Thrift介绍1.什么是thrift?thrift早期由facebook内部团队开发,主要用于实现跨语言间的方法调用,属于远程方法调用的一种,后开源纳入apache中,成为了apache thrif ...
- 一文了解:Redis基础类型
Redis基础类型 Redis特点 开源的,BSD许可高级的key-value存储系统 可以用来存储字符串,哈希结构,链表,集合 安装 windows:https://github.com/micro ...
- 夯实Java基础(二)——面向对象之封装
1.封装介绍 封装封装,见名知意,就是把东西包装隐藏起来,不被外界所看见, 而Java特性封装:是指利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体,数据被保护在抽象数 ...
- npm包开发与发布
把通用的功能开发成npm包,便用使用和维护,更重要的是可以分享给广大的开发者,是不是很激动人心! 那么,步骤如下: 1.创建项目 创建项目目录,npm init ,根据需要输入配置信息(建完后也可以在 ...
- 最基础的 ant build 脚本
最基础的 ant build 脚本,根据项目,自行进行修改 <?xml version="1.0" encoding="UTF-8" ?> < ...
- Linux curl 命令详解
命令概要 该命令设计用于在没有用户交互的情况下工作. curl 是一个工具,用于传输来自服务器或者到服务器的数据.「向服务器传输数据或者获取来自服务器的数据」 可支持的协议有(DICT.FILE.FT ...