CodeForces - 1108E2 Array and Segments (Hard version)

E2. Array and Segments (Hard version)

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

The only difference between easy and hard versions is a number of elements in the array.

You are given an array aa consisting of nn integers. The value of the ii-th element of the array is aiai.

You are also given a set of mm segments. The jj-th segment is [lj;rj][lj;rj], where 1≤lj≤rj≤n1≤lj≤rj≤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]a=[0,0,0,0,0] and the given segments are [1;3][1;3] and [2;4][2;4] then you can choose both of them and the array will become b=[−1,−2,−2,−1,0]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 aa and obtain the array bb then the value maxi=1nbi−mini=1nbimaxi=1nbi−mini=1nbi 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 nn and mm (1≤n≤105,0≤m≤3001≤n≤105,0≤m≤300) — the length of the array aa and the number of segments, respectively.

The second line of the input contains nn integers a1,a2,…,ana1,a2,…,an (−106≤ai≤106−106≤ai≤106), where aiai is the value of the ii-th element of the array aa.

The next mm lines are contain two integers each. The jj-th of them contains two integers ljlj and rjrj (1≤lj≤rj≤n1≤lj≤rj≤n), where ljlj and rjrjare the ends of the jj-th segment.

Output

In the first line of the output print one integer dd — the maximum possible value maxi=1nbi−mini=1nbimaxi=1nbi−mini=1nbi if bb is the array obtained by applying some subset of the given segments to the array aa.

In the second line of the output print one integer qq (0≤q≤m0≤q≤m) — the number of segments you apply.

In the third line print qq distinct integers c1,c2,…,cqc1,c2,…,cq in any order (1≤ck≤m1≤ck≤m) — indices of segments you apply to the array aa in such a way that the value maxi=1nbi−mini=1nbimaxi=1nbi−mini=1nbi of the obtained array bb is maximum possible.

If there are multiple answers, you can print any.

Examples

input

Copy

5 4
2 -2 3 1 2
1 3
4 5
2 5
1 3

output

Copy

6
2
1 4 

input

Copy

5 4
2 -2 3 1 4
3 5
3 4
2 4
2 5

output

Copy

7
2
2 3 

input

Copy

1 0
1000000

output

Copy

0
0

Note

In the first example the obtained array bb will be [0,−4,1,1,2][0,−4,1,1,2] so the answer is 66.

In the second example the obtained array bb will be [2,−3,1,−1,4][2,−3,1,−1,4] so the answer is 77.

In the third example you cannot do anything so the answer is 00.

 

 

这个题和e1一样,只是n由300 变为了1e5。

比赛的时候e1我是枚举两个点,然后把包含了这个点的区间全部加进去,直接暴力求ans,复杂度为O(N^2 * M)。

然后做e2的时候想过用线段树维护一个最大值,优化到O(nmlogn),感觉似乎要用可持久化线段树,而且当时看了一眼F题,没有思路,发现F过的人比E2还多其实是因为太困了,就放弃了。

结果我当时的思路是正确的。。只是一些细节没有去考虑,如果当时运气好过了这道题,大概能打到30名吧一个div3我在激动啥

 

 

枚举每个点,把包含这个点的所有边加上,把之前加了但是现在不包含这个点的边删除,直接上线段树维护就可以了。

#include<cstdio>
#include<cstring>
#include<iostream>
#include "algorithm"
#include "queue"
#include "unordered_map"
#include "bits/stdc++.h"
#define LOGN 10
#define MAXN (1<<LOGN)
#define MAXNODES 3*( (1<<(2*LOGN)) / 4 + 100)
#define son(x) (p*4-2+x)
using namespace std;
const int mod = 20071027;

int a[100004];
struct line
{
    int l,r,id;
    bool friend operator < (line a ,line b)
    {
        if(a.l==b.l)return a.r<b.r;
        else return a.l<b.l;
    }
}l[304],r[304];

struct node
{
    int l,r,w,laz;
}t[400004];

void build(int rt,int l,int r)
{
    t[rt]={l,r,0,0};
    if(l==r)t[rt].w=a[l];
    else {
        int mid=(l+r)>>1;
        build(rt<<1,l,mid);
        build(rt<<1|1,mid+1,r);
        t[rt].w=max(t[rt<<1].w,t[rt<<1|1].w);
    }
}

void pushdown(int rt)
{
    if(t[rt].laz==0)return ;
    t[rt<<1].laz+=t[rt].laz;
    t[rt<<1|1].laz+=t[rt].laz;
    t[rt<<1].w+=t[rt].laz;
    t[rt<<1|1].w+=t[rt].laz;
    t[rt].laz=0;
}

void update(int rt,int l,int r,int w)
{
    if(t[rt].l>=l&&t[rt].r<=r)
    {
        t[rt].laz+=w;
        t[rt].w+=w;
    } else{
        pushdown(rt);
        int mid=(t[rt].l+t[rt].r)>>1;
        if(l<=mid)update(rt<<1,l,r,w);
        if(r>mid)update(rt<<1|1,l,r,w);
        t[rt].w=max(t[rt<<1].w,t[rt<<1|1].w);
    }
}
int main()
{
    int n,m;
    cin>>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].l,&l[i].r);
        l[i].id=i;
        r[i]=l[i];
    }
    sort(l+1,l+1+m);
    build(1,1,n);
    int cnt1=1,cnt2=1;
    int ans=-1000000000;
    vector<int>v;
    vector<int>ansv;
    for (int i = 1; i <= n; ++i) {
        //这里加区间删区间可以用优先队列优化
        while(cnt2<=m&&l[cnt2].l<=i)
        {
            update(1,l[cnt2].l,l[cnt2].r,-1);
            v.push_back(l[cnt2].id);
            cnt2++;
        }
        for (int j = 0; j < v.size(); ++j) {
            if(r[v[j]].r<i){
                update(1,r[v[j]].l,r[v[j]].r,1);
                v.erase(v.begin()+j);
                j--;
            }
        }
        if(ans<t[1].w-a[i]+(int)v.size())
        {
            ans=t[1].w-a[i]+(int)v.size();
            ansv=v;
        }
    }
    if(ans==-1000000000)
    {
        puts("0");
        puts("0");
        return 0;
    }
    printf("%d\n",ans);printf("%d\n",ansv.size());
    if(ansv.size()>0)
    {

        for (int i = 0; i < ansv.size(); ++i){
            printf("%d ",ansv[i]);
        }
    }
}

 

 

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值