【Codeforces 1108 E2. Array and Segments (Hard version) 】线段树

E2

题意和E1一样 就是n变成了 1e5 那么我们就不能像E1一样使用 n^2 * m的算法了

我们考虑一下这个问题 E1是 n^2的枚举最小值

我们E2也是去枚举最小值 我们发现如果最大值和最小值都在一个区间内 你操作这个区间也就是区间减1是不会对答案产生影响的

如果最小值在 最大值不在 那么操作这个区间会使得答案 + 1

如果最大值在 最小值不在 那么操作这个区间会使得答案 - 1

所以实际上就是让你操作包含这个最小值位置 的 区间 注意一定不能二维排序 因为可能不满足 或者满足了我是用双指针就WA 13了

这样的话你建立两个vector 一个存以 i 开始的那个区间的右端

一个存以 i 为右端点的那个区间的左端

那么就可以枚举的方法做出答案了

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <stack>
#include <cmath>
#include <map>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;

#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
const int MAX_N = 100025;
queue<int > anss,tmp;
vector<int > st[MAX_N],ed[MAX_N];
int arr[MAX_N];
int maxx[MAX_N<<2],col[MAX_N<<2];
struct node
{
    int l,r;
}Q[MAX_N];
void up(int rt)
{
    maxx[rt] = max(maxx[rt<<1],maxx[rt<<1|1]);
}
void down(int rt,int l,int r)
{
    if(col[rt])
    {
        int mid = (l+r)>>1;
        col[rt<<1] += col[rt];
        col[rt<<1|1] += col[rt];
        maxx[rt<<1] += col[rt];
        maxx[rt<<1|1] += col[rt];
        col[rt] = 0;
    }
}
void build(int rt,int l,int r)
{
    col[rt] = 0;
    if(l==r)
    {
        scanf("%d",&maxx[rt]);
        return ;
    }
    int mid = (l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    up(rt);
}
void update(int rt,int l,int r,int x,int y,int v)
{
    if(x<=l&&r<=y)
    {
        col[rt] += v;
        maxx[rt] += v;
        return ;
    }
    down(rt,l,r);
    int mid = (l+r)>>1;
    if(x<=mid) update(rt<<1,l,mid,x,y,v);
    if(mid<y) update(rt<<1|1,mid+1,r,x,y,v);
    up(rt);
}
int query(int rt,int l,int r,int x,int y)
{
    if(x<=l&&r<=y)
    {
        return maxx[rt];
    }
    int mid = (l+r)>>1,maxx1 = -10000000,maxx2 = -10000000;
    down(rt,l,r);
    if(x<=mid) maxx1 = query(rt<<1,l,mid,x,y);
    if(mid<y) maxx2 = query(rt<<1|1,mid+1,r,x,y);
    return max(maxx1,maxx2);
}
int main()
{
    int n,m,xb,ans = -1,maxx_ = -10000000,minn = 10000000,a,b;
    scanf("%d%d",&n,&m);
    build(1,1,n);
    for(int i = 1;i<=m;++i)
    {
        scanf("%d%d",&Q[i].l,&Q[i].r);
        st[Q[i].l].push_back(Q[i].r);
        ed[Q[i].r].push_back(Q[i].l);
    }
    for(int i = 1;i<=n;++i)
    {
        for(int j = 0;j<st[i].size();j++)
            update(1,1,n,i,st[i][j],-1);
        int tmp = query(1,1,n,1,n) - query(1,1,n,i,i);
        if(ans<tmp)
        {
            ans = tmp;
            xb = i;
        }
        for(int j = 0;j<ed[i].size();j++)
            update(1,1,n,ed[i][j],i,1);
    }
    for(int i = 1;i<=m;++i)
        if(Q[i].l<=xb&&Q[i].r>=xb) anss.push(i);
    printf("%d\n",ans);
    printf("%d\n",anss.size());
    int sz = anss.size();
    for(int i = 1;i<=sz;++i)
    {
        int now = anss.front();
        printf("%d",now);
        anss.pop();
        i==sz?printf("\n"):printf(" ");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/heucodesong/article/details/88712506