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,请选择一些操作(可以都不选),使得序列的最大值和最小值的差值尽量的大. 思路:容易发现如果最大值和最小值都 ...
随机推荐
- bootstrap table api
http://blog.csdn.net/rickiyeat/article/details/56483577
- [2011山东ACM省赛] Binomial Coeffcients(求组合数)
Binomial Coeffcients nid=24#time" style="padding-bottom:0px; margin:0px; padding-left:0px; ...
- xpath 轴,节点之间的关系
http://www.w3school.com.cn/xpath/xpath_axes.asp http://www.freeformatter.com/xpath-tester.html 测试 轴可 ...
- TCP协议和socket API 学习笔记
本文转载至 http://blog.chinaunix.net/uid-16979052-id-3350958.html 分类: 原文地址:TCP协议和socket API 学习笔记 作者:gilb ...
- mac 权限问题
终端输入sudo chown -R zjtc /usr/local
- libcurl以get方式请求服务器端文件
static size_t callbackfunction(void *ptr, size_t size, size_t nmemb, void* userdata){ FILE* strea ...
- 【操作系统】使用BCD工具安装Ubuntu操作系统
Ubuntu14.04作为目前最新版本的ubuntu系统,相信很多人都想在自己的电脑上安装一下,然而系统的安装方法各式各样,U盘法.grub引导法等等,本文将介绍在win7系统下用easyBCD软件建 ...
- Hamming校验码
可参考:http://winda.blog.51cto.com/55153/1068000 Hamming校验码作用:用于校验通信数据,防止出现错误,并具有一定的纠错功能. 汉明码在传输的消息流中插入 ...
- LightOJ1245 Harmonic Number (II) —— 规律
题目链接:https://vjudge.net/problem/LightOJ-1245 1245 - Harmonic Number (II) PDF (English) Statistics ...
- PYTHON 爬虫笔记一:爬虫基本原理梳理
知识点一:爬虫的基本原理梳理 一.什么是爬虫? 请求网站并提取数据的自动化程序 二.爬虫的基本流程 1:向服务器发起请求 通过HTTP库向目标站点发起请求,即发送一个Request,请求可以包含额外的 ...