CF1108E2 Array and Segments (Hard version)
2024-08-27 19:55:24
线段树
对于$Easy$ $version$可以枚举极大值和极小值的位置,然后判断即可
但对于$Hard$ $version$明显暴力同时枚举极大值和极小值会超时
那么,考虑只枚举极小值
对于数轴上每一个点,记录开始和结束于这个点的区间
那么从1枚举到i时可以处理出当包含i点所有区间
所以用线段树维护修改这些区间,进行判断总区间的极差
记录最大值即可
#include <bits/stdc++.h>
using namespace std;
const int MAXN=1e5+100;
int n,m,a[MAXN],l[310],r[310];
int ans,wh;
vector <int> t,be[MAXN],ed[MAXN];
struct node
{
int l,r,MAX,MIN,sum,lazy;
}sh[MAXN*4];
void pushup(int x)
{
sh[x].sum=sh[x+x].sum+sh[x+x+1].sum;
sh[x].MAX=max(sh[x+x].MAX,sh[x+x+1].MAX);
sh[x].MIN=min(sh[x+x].MIN,sh[x+x+1].MIN);
}
void pushdown(int x)
{
if (sh[x].lazy!=0)
{
sh[x+x].lazy+=sh[x].lazy;
sh[x+x+1].lazy+=sh[x].lazy;
sh[x+x].sum+=sh[x].lazy;
sh[x+x].MAX+=sh[x].lazy;
sh[x+x].MIN+=sh[x].lazy;
sh[x+x+1].sum+=sh[x].lazy;
sh[x+x+1].MAX+=sh[x].lazy;
sh[x+x+1].MIN+=sh[x].lazy;
sh[x].lazy=0;
}
}
void build(int x,int ll,int rr)
{
sh[x].l=ll;
sh[x].r=rr;
if (ll==rr)
{
sh[x].MAX=sh[x].MIN=sh[x].sum=a[ll];
return;
}
int mid;
mid=(ll+rr)>>1;
build(x+x,ll,mid);
build(x+x+1,mid+1,rr);
pushup(x);
}
void change(int x,int ll,int rr,int k)//区间修改
{
if (sh[x].l>=ll && sh[x].r<=rr)
{
sh[x].sum+=k;
sh[x].MIN+=k;
sh[x].MAX+=k;
sh[x].lazy+=k;
return;
}
pushdown(x);
int mid;
mid=(sh[x].l+sh[x].r)>>1;
if (ll<=mid)
change(x+x,ll,rr,k);
if (rr>mid)
change(x+x+1,ll,rr,k);
pushup(x);
}
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]);
build(1,1,n);
if (n==1)
{
printf("0\n0\n");
return 0;
}
for (int i=1;i<=m;i++)
{
be[l[i]].push_back(i);//对于结束和开始的节点记录区间
ed[r[i]].push_back(i);
}
ans=sh[1].MAX-sh[1].MIN;
wh=0;
for (int i=1;i<=n;i++)
{
for (int j=0;j<(int)ed[i-1].size();j++)
{
int u;
u=ed[i-1][j];
change(1,l[u],r[u],1);//将之前修改的区间对当前无影响改回去
}
for (int j=0;j<(int)be[i].size();j++)
{
int u;
u=be[i][j];
change(1,l[u],r[u],-1);//将新增的区间修改
}
pushdown(1);
pushup(1);
if (sh[1].MAX-sh[1].MIN>ans)//记录当期的极差
{
ans=sh[1].MAX-sh[1].MIN;
wh=i;
}
}
for (int i=1;i<=m;i++)
{
if (l[i]<=wh && r[i]>=wh)
t.push_back(i);
}
printf("%d\n%d\n",ans,(int)t.size());
for (int i=0;i<(int)t.size();i++)
printf("%d ",t[i]);
printf("\n");
}
最新文章
- 初识 Html5
- CSS3--box-shadow
- Xcode导航栏不显示模拟器选择框ToolBar
- 怎么搭建Web Api
- poj 2503:Babelfish(字典树,经典题,字典翻译)
- Sprint总结和第八九十的读书笔记
- JDK自带工具一览表。妈妈再也不用担心你到处去下载小软件了~~
- 用c/c++混合编程方式为ios/android实现一个自绘日期选择控件(一)
- 微课程--Android--Android开发学习体系
- cojs 简单的最近公共祖先 解题报告
- 【网络流24题】No.19 负载平衡问题 (费用流)
- mongoose 查询子文档的方法
- 《JavaScript+DOM编程艺术》的摘要(五)-----添加insertAfter
- 无法识别的属性“targetFramework”。请注意,属性名是大写和小写。错误的解决方案
- Sass与Compress实战:第二章
- 【Electron】Electron开发入门(三):main process和web page 通信
- Luogu P3371 【模板】单源最短路径
- Flutter 初尝:从 Java 无缝过渡
- B+树介绍
- 结构化您的Python工程