codeforces#1108E2. Array and Segments (线段树+扫描线)
题目链接:
http://codeforces.com/contest/1108/problem/E2
题意:
给出$n$个数和$m$个操作
每个操作是下标为$l$到$r$的数减一
选出某些操作,使$n$个数的最大值减最小值最大
数据范围:
$1 \le n \le 10^5$
$0 \le m \le 300$
$-10^6 \le a_i \le 10^6$
分析:
假设选择第$i$位置作为最小值,那么我们选取所有包含$i$的区间可以得到选择第$i$位置为最小值的最佳答案
第一步,我们从$1$到$n$枚举最小值的位置
第二步,我们用扫描线来添加和减少题目给出的区间影响,例如最小值为$i$时,我们要让所有的包含i区间的操作生效
第三步,计算以$i$为最小值时的最优解
ac代码:
#include<bits/stdc++.h>
#define ll long long
#define pa pair<int,int>
using namespace std;
const int maxn=1e5+10;
const int maxm=300+10;
const ll mod=1e9+7;
int ans=-1,inde,tree[maxn*4],lazy[maxn*4],num[maxn],n;
pa quer[maxm];
vector<pa>ve[maxn];
vector<int>ve2;
void build(int st,int en,int rt)
{
if(st==en)
{
tree[rt]=num[st];
return ;
}
int md=(st+en)/2;
build(st,md,rt*2);
build(md+1,en,rt*2+1);
tree[rt]=max(tree[rt*2],tree[rt*2+1]);
}
void update(int l,int r,int x,int st,int en,int rt)
{
if(l>en||r<st)return ;
if(l<=st&&r>=en)
{
lazy[rt]+=x;
tree[rt]+=x;
return ;
}
if(lazy[rt])
{
int v=lazy[rt];
lazy[rt*2]+=v;
lazy[rt*2+1]+=v;
tree[rt*2]+=v;
tree[rt*2+1]+=v;
lazy[rt]=0;
}
int md=(st+en)/2;
update(l,r,x,st,md,rt*2);
update(l,r,x,md+1,en,rt*2+1);
tree[rt]=max(tree[rt*2],tree[rt*2+1]);
}
int Quer(int x,int st,int en,int rt)
{
if(st==en)
return tree[rt];
if(lazy[rt])
{
int v=lazy[rt];
lazy[rt*2]+=v;
lazy[rt*2+1]+=v;
tree[rt*2]+=v;
tree[rt*2+1]+=v;
lazy[rt]=0;
}
int md=(st+en)/2;
int res;
if(x<=md)res=Quer(x,st,md,rt*2);
else res=Quer(x,md+1,en,rt*2+1);
tree[rt]=max(tree[rt*2],tree[rt*2+1]);
return res;
}
int main()
{
int q;
scanf("%d %d",&n,&q);
for(int i=1;i<=n;i++)
scanf("%d",&num[i]);
build(1,n,1);
for(int i=1;i<=q;i++)
{
int l,r;
scanf("%d %d",&l,&r);
quer[i].first=l;
quer[i].second=r;
ve[l].push_back(make_pair(i,-1));
ve[r+1].push_back(make_pair(i,+1));
}
for(int i=1;i<=n;i++)
{
for(int j=0;j<ve[i].size();j++)
{
int v=ve[i][j].first;
int add=ve[i][j].second;
update(quer[v].first,quer[v].second,add,1,n,1);
}
int res=tree[1]-Quer(i,1,n,1);
if(res>ans)
{
inde=i;
ans=res;
}
}
printf("%d\n",ans);
int res=0;
for(int i=1;i<=q;i++)
if(inde>=quer[i].first&&inde<=quer[i].second)
ve2.push_back(i);
printf("%d\n",ve2.size());
for(int i=0;i<ve2.size();i++)
printf("%d%c",ve2[i]," \n"[i==ve2.size()-1]);
return 0;
}
codeforces#1108E2. Array and Segments (线段树+扫描线)的更多相关文章
- Codeforces 1108E (Array and Segments) 线段树
题意:给你一个长度为n的序列和m组区间操作,每组区间操作可以把区间[l, r]中的数字都-1,请选择一些操作(可以都不选),使得序列的最大值和最小值的差值尽量的大. 思路:容易发现如果最大值和最小值都 ...
- Codeforces Round #337 (Div. 2) D. Vika and Segments 线段树扫描线
D. Vika and Segments 题目连接: http://www.codeforces.com/contest/610/problem/D Description Vika has an i ...
- Codeforces Round #337 (Div. 2) D. Vika and Segments (线段树+扫描线+离散化)
题目链接:http://codeforces.com/contest/610/problem/D 就是给你宽度为1的n个线段,然你求总共有多少单位的长度. 相当于用线段树求面积并,只不过宽为1,注意y ...
- Codeforces 1108E2 Array and Segments (Hard version) 差分, 暴力
Codeforces 1108E2 E2. Array and Segments (Hard version) Description: The only difference between eas ...
- Codeforces 1108E2 Array and Segments (Hard version)(差分+思维)
题目链接:Array and Segments (Hard version) 题意:给定一个长度为n的序列,m个区间,从m个区间内选择一些区间内的数都减一,使得整个序列的最大值减最小值最大. 题解:利 ...
- Codeforces 610D Vika and Segments 线段树+离散化+扫描线
可以转变成上一题(hdu1542)的形式,把每条线段变成宽为1的矩形,求矩形面积并 要注意的就是转化为右下角的点需要x+1,y-1,画一条线就能看出来了 #include<bits/stdc++ ...
- Codeforces VK CUP 2015 D. Closest Equals(线段树+扫描线)
题目链接:http://codeforces.com/contest/522/problem/D 题目大意: 给你一个长度为n的序列,然后有m次查询,每次查询输入一个区间[li,lj],对于每一个查 ...
- Codeforces Round #337 (Div. 2) D. Vika and Segments 线段树 矩阵面积并
D. Vika and Segments Vika has an infinite sheet of squared paper. Initially all squares are whit ...
- hdu 1828 线段树扫描线(周长)
Picture Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Sub ...
随机推荐
- How does a browser know which response belongs to which request?
Today I knows that the server never send a request to a client! It just make response~ So,if the bro ...
- Go入门所踩过的坑:cannot find package "" in any of
问题:cannot find package "" in any of.现已按照博客解决,分享一种自己踩得坑欢迎大神指导交流! 首先使用go env查看当前环境变量,新手入门出现找 ...
- POJ 1789 Prim
给定N个字符串,某个字符串转为另一个字符串的花费为他们每一位不相同的字符数. 求最小花费Q. Input 多组输入,以0结束. 保证N不超过2000. Output 每组输出"The hig ...
- SMTP实现发送邮箱2(封装版)
SMTP.h #ifndef __SMTP_H__ //避免重复包含 #define __SMTP_H__ #include <iostream> #include <list> ...
- 工作单元 — Unit Of Work
在进行数据库添加.修改.删除时,为了保证事务的一致性,即操作要么全部成功,要么全部失败.例如银行A.B两个账户的转账业务.一方失败都会导致事务的不完整性,从而事务回滚.而工作单元模式可以跟踪事务,在操 ...
- 手机号码归属地查询API
<?php function object_array($array){ if(is_object($array)){ $array = (array)$array; } if(is_array ...
- 在开源UOJ的导航栏中添加新页面链接
前言 刚用开源UOJ搭建OJ成功时就想在导航栏那里添加一个站内页面链接,无奈当时乱搞水平低,网上也没有教程,不晓得怎么弄 今天突然来了闲情乱搞一通,结果还真乱搞成了...特意写下为后来人少走点弯路 前 ...
- Ubuntu18.04安装MySQL与默认编码设置
安装 打开终端直接开始,编码配置方法在后面 #通过apt更新包索引 sudo apt update #按照默认软件包安装 sudo apt install mysql-server #运行安全脚本 s ...
- 关于SpringBoot的自动配置和启动过程
一.简介 Spring Boot简化了Spring应用的开发,采用约定大于配置的思想,去繁从简,很方便就能构建一个独立的.产品级别的应用. 1.传统J2EE开发的缺点 开发笨重.配置繁多复杂.开发效率 ...
- SSM框架警告/错误集合
警告: 1.使用Eclipse的Spring Elements组件的时候发现会提示有警告:Expect at least one bean match() 解决办法:项目可以正常运行,未有报错,在其他 ...