Codeforces 1108E2 Array and Segments (Hard version) 差分, 暴力
Codeforces 1108E2
E2. Array and Segments (Hard version)
Description:
The only difference between easy and hard versions is a number of elements in the array.
You are given an array \(a\) consisting of \(n\) integers. The value of the \(i\)-th element of the array is \(a_i\).
You are also given a set of \(m\) segments. The \(j\)-th segment is \([l_j; r_j]\), where \(1 \le l_j \le r_j \le n\).
You can choose some subset of the given set of segments and decrease values on each of the chosen segments by one (independently). For example, if the initial array \(a = [0, 0, 0, 0, 0]\) and the given segments are \([1; 3]\) and \([2; 4]\) then you can choose both of them and the array will become \(b = [-1, -2, -2, -1, 0]\).
You have to choose some subset of the given segments (each segment can be chosen at most once) in such a way that if you apply this subset of segments to the array \(a\) and obtain the array \(b\) then the value \(\max\limits_{i=1}^{n}b_i - \min\limits_{i=1}^{n}b_i\) will be maximum possible.
Note that you can choose the empty set.
If there are multiple answers, you can print any.
If you are Python programmer, consider using PyPy instead of Python when you submit your code.
Input:
The first line of the input contains two integers \(n\) and \(m\) (\(1 \le n \le 10^5, 0 \le m \le 300\)) — the length of the array \(a\) and the number of segments, respectively.
The second line of the input contains \(n\) integers \(a_1, a_2, \dots, a_n\) (\(-10^6 \le a_i \le 10^6\)), where \(a_i\) is the value of the \(i\)-th element of the array \(a\).
The next \(m\) lines are contain two integers each. The \(j\)-th of them contains two integers \(l_j\) and \(r_j\) (\(1 \le l_j \le r_j \le n\)), where \(l_j\) and \(r_j\) are the ends of the \(j\)-th segment.
Output
In the first line of the output print one integer \(d\) — the maximum possible value \(\max\limits_{i=1}^{n}b_i - \min\limits_{i=1}^{n}b_i\) if \(b\) is the array obtained by applying some subset of the given segments to the array \(a\).
In the second line of the output print one integer \(q\) (\(0 \le q \le m\)) — the number of segments you apply.
In the third line print \(q\) distinct integers \(c_1, c_2, \dots, c_q\) in any order (\(1 \le c_k \le m\)) — indices of segments you apply to the array \(a\) in such a way that the value \(\max\limits_{i=1}^{n}b_i - \min\limits_{i=1}^{n}b_i\) of the obtained array \(b\) is maximum possible.
If there are multiple answers, you can print any.
Sample Input:
5 4
2 -2 3 1 2
1 3
4 5
2 5
1 3
Sample Output:
6
2
4 1
Sample Input:
5 4
2 -2 3 1 4
3 5
3 4
2 4
2 5
Sample Output:
7
2
3 2
Sample Input:
1 0
1000000
Sample Output:
0
0
题目链接
题解:
有一个长为\(n\)的数列,有\(m\)个线段,每个线段将该线段区间的所有数减一,你可以选任意个线段,要求最大化极差并输出一种方案
这种极差的题一个套路是固定最大值求最小值
那么我们可以枚举每一个数作为最大值的方案,对不包含这个数的线段进行操作,然后找最大最小值即可,利用差分的思想单次操作可以\(O(1)\),最后查询极值\(O(n)\),这样我们就找到了一个\(O(n^2)\)的优秀算法,可以通过这题的简单版本
然后我们注意到线段数很少,只有\(300\)个,那么我们可以将原数列分为至多\(600\)段,每一段的数作为最大值时策略是相同的,我们就的到了\(O(n \cdot m +m^2)\)的算法,cf机子上跑得飞快
另外,可以用线段树加速操作得到\(O(mlog(n))\)的做法
甚至可以将\(n\)也变成\(m\),因为我们只关心每一段的极值,可以把原数列切成至多\(600\)段,每一段记录最大最小值即可,复杂度为\(O(m^2)\), 不知道为什么评论指出这个算法的老哥的代码跑的还没我\(O(n \cdot m + m^2)\)快...
AC代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10, M = 310;
int n, a[N], b[N], ans, l[M], r[M], m, rec, cnt;
set<int> key;
int main() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i)
scanf("%d", &a[i]);
for(int i = 1; i <= m; ++i) {
scanf("%d%d", &l[i], &r[i]);
key.insert(l[i]);
key.insert(r[i] + 1);
}
ans = *max_element(a + 1, a + n + 1) - *min_element(a + 1, a + n + 1);
for(auto it = key.begin(); it != key.end(); ++it) {
int i = *it; ++cnt;
memset(b, 0, sizeof(b));
int mx = -1e9, mn = 1e9, sum = 0;
for(int j = 1; j <= m; ++j) {
if(l[j] <= i && i <= r[j]) continue;
b[l[j]]--, b[r[j] + 1]++;
}
for(int j = 1; j <= n; ++j) {
sum += b[j];
mx = max(mx, a[j] + sum);
mn = min(mn, a[j] + sum);
}
if(mx - mn > ans) {
rec = i;
ans = mx - mn;
}
}
printf("%d\n", ans);
if(rec) {
vector<int> res;
for(int i = 1; i <= m; ++i) {
if(l[i] <= rec && rec <= r[i]) continue;
res.push_back(i);
}
printf("%d\n", (int)res.size());
for(int i = 0; i < res.size(); ++i)
printf("%d%c", res[i], " \n"[i == res.size() - 1]);
}
else
puts("0\n");
return 0;
}
Codeforces 1108E2 Array and Segments (Hard version) 差分, 暴力的更多相关文章
- Codeforces 1108E2 Array and Segments (Hard version)(差分+思维)
题目链接:Array and Segments (Hard version) 题意:给定一个长度为n的序列,m个区间,从m个区间内选择一些区间内的数都减一,使得整个序列的最大值减最小值最大. 题解:利 ...
- codeforces#1108E2. Array and Segments (线段树+扫描线)
题目链接: http://codeforces.com/contest/1108/problem/E2 题意: 给出$n$个数和$m$个操作 每个操作是下标为$l$到$r$的数减一 选出某些操作,使$ ...
- E1. Array and Segments (Easy version)(暴力) && E2. Array and Segments (Hard version)(线段树维护)
题目链接: E1:http://codeforces.com/contest/1108/problem/E1 E2:http://codeforces.com/contest/1108/problem ...
- Codeforces Round #535 (Div. 3) E2. Array and Segments (Hard version) 【区间更新 线段树】
传送门:http://codeforces.com/contest/1108/problem/E2 E2. Array and Segments (Hard version) time limit p ...
- CF1108E2 Array and Segments (Hard version)
线段树 对于$Easy$ $version$可以枚举极大值和极小值的位置,然后判断即可 但对于$Hard$ $version$明显暴力同时枚举极大值和极小值会超时 那么,考虑只枚举极小值 对于数轴上每 ...
- Array and Segments (Easy version) CodeForces - 1108E1 (暴力枚举)
The only difference between easy and hard versions is a number of elements in the array. You are giv ...
- 【Codeforces 1108E1】Array and Segments (Easy version)
[链接] 我是链接,点我呀:) [题意] 题意 [题解] 枚举最大值和最小值在什么地方. 显然,只要包含最小值的区间,都让他减少. 因为就算那个区间包含最大值,也无所谓,因为不会让答案变小. 但是那些 ...
- CF E2 - Array and Segments (Hard version) (线段树)
题意给定一个长度为n的序列,和m个区间.对一个区间的操作是:对整个区间的数-1可以选择任意个区间(可以为0个.每个区间最多被选择一次)进行操作后,要求最大化的序列极差(极差即最大值 - 最小值).ea ...
- Codeforces 1108E (Array and Segments) 线段树
题意:给你一个长度为n的序列和m组区间操作,每组区间操作可以把区间[l, r]中的数字都-1,请选择一些操作(可以都不选),使得序列的最大值和最小值的差值尽量的大. 思路:容易发现如果最大值和最小值都 ...
随机推荐
- python(11)- 文件处理
文件操作 1.1 对文件操作流程 打开文件,得到文件句柄并赋值给一个变量 通过句柄对文件进行操作 关闭文件 现有文件如下: 昨夜寒蛩不住鸣. 惊回千里梦,已三更. 起来独自绕阶行. 人悄悄,帘外月胧明 ...
- Android 5.0状态栏和导航栏
Material Design推出之后,app中也開始沿用这样的风格 今天来说一下状态栏颜色设置,在4.4的时候推出了透明状态栏和导航栏.在不使用第三方库的情况下,4.4还是没有全然解决存在actio ...
- 后台运行命令:&和nohup command & 以及关闭、查看后台任务
当我们在终端或控制台工作时.可能不希望由于执行一个作业而占住了屏幕,由于可能还有更重要的事情要做,比方阅读电子邮件. 对于密集訪问磁盘的进程,我们更希望它可以在每天的非负荷高峰时间段执行(比如凌晨). ...
- 浅析嵌入式C优化技巧
嵌入式C语言优化小技巧 1 概述 嵌入式系统是指完毕一种或几种特定功能的计算机系统,具有自己主动化程度高,响应速度快等长处,眼下已广泛应用于消费电子,工业控制等领域.嵌入式系统受其使用的硬件以及运行环 ...
- ubuntu 安装后的配置
osx 下用 vmware 安装了一个 ubuntu 虚拟机,版本是 14.04 server.安装完之后要做一系列配置,记录如下. 配置 Android 编译环境 sudo apt-get inst ...
- #include <sys/socket.h>找不到头文件
ubuntu下socket编程涉及到头文件sys/socket.h 和sys/types.h.我是用的codeblocks编辑器,当我想查看socket,h头文件时编辑器提示找不到头文件. 我就想可能 ...
- php 面向对象的三大要素(封装、继承、多态)以及重写(override)和重载(overload)的举例说明
PHP是一种HTML内嵌式的,用来制作动态网页的服务器端的脚本语言.其特点是:开发周期短,稳定安全,简单易学,免费开源,良好的跨平台特性.PHP是一种面向对象的程序设计语言,目前已成为全球最受欢迎的五 ...
- android打包签名,从生成keystore到完成签名
输入指令并获得结果:(对应自己的java安装目录) 首先,我们需要一个keystore,当然已经有了的话就不用这一步了:cmd下:进入到jdk的bin目录,这样的话,android.keystore文 ...
- ftp上传文件不能上传到指定的文件夹
首先是,使用ftp创建连接,这一点没有错误,但是在切换目录创建文件夹的时候出现了问题. 指定创建的文件夹,总是创建失败,切换目录同样失败.最后查看文件夹的权限才知道,没有权限的问题: 然后给img文件 ...
- java使用ftp局域网内多线程上传图片过慢
多线程ftp上传文件时候,图片上传很慢,调试和查询资料发现主要在:storeFile方法 解决方案如下: FTPClient fc设置setBufferSize 可以根据内存大小适当设置大点的缓冲区: ...