CF #535 (Div. 3) E2 Array and Segments (Hard version) 利用线段树进行区间转移

传送门

题意:

有m个区间,n个$a[ i ]$ , 选择若干个区间,使得整个数组中的最大值和最小值的差值最小。n<=1e5,m<=300;

思路:

可以知道每个i,如果一个区间包含这个点,就让这个区间发挥作用。枚举每个i,找到最大值即可。

当然这个复杂度不对,我们可以通过线段树保存数组的最大值和最小值,每次区间在左端点发挥作用,在右端点去掉作用。

#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>

using namespace std;
#define lson (l , mid , rt << 1)
#define rson (mid + 1 , r , rt << 1 | 1)
#define debug(x) cerr << #x << " = " << x << "\n";
#define pb push_back
#define pq priority_queue



typedef long long ll;
typedef unsigned long long ull;
//typedef __int128 bll;
typedef pair<ll ,ll > pll;
typedef pair<int ,int > pii;
typedef pair<int,pii> p3;
typedef pair<ll,int>pli;
//priority_queue<int> q;//这是一个大根堆q
//priority_queue<int,vector<int>,greater<int> >q;//这是一个小根堆q
#define fi first
#define se second
//#define endl '\n'
//#define R register
#define OKC ios::sync_with_stdio(false);cin.tie(0)
#define FT(A,B,C) for(int A=B;A <= C;++A)  //用来压行
#define REP(i , j , k)  for(int i = j ; i <  k ; ++i)
#define max3(a,b,c) max(max(a,b), c);
#define min3(a,b,c) min(min(a,b), c);
//priority_queue<int ,vector<int>, greater<int> >que;

const ll mos = 0x7FFFFFFF;  //2147483647
const ll nmos = 0x80000000;  //-2147483648
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f; //18
//const int mod = 1e9+7;
const double esp = 1e-8;
const double PI=acos(-1.0);
const double PHI=0.61803399;    //黄金分割点
const double tPHI=0.38196601;


template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}


/*-----------------------showtime---------------------*/


            const int maxn = 1e5+9;
            int mx[maxn<<2],mn[maxn<<2],dif[maxn<<2];
            int lazy[maxn<<2];

            int a[maxn];
            pii e[maxn];
            void pushup(int rt){
                mx[rt] = max(mx[rt<<1], mx[rt<<1|1]);
                mn[rt] = min(mn[rt<<1], mn[rt<<1|1]);
                dif[rt] = mx[rt] - mn[rt];
            }
            void build(int l,int r,int rt){
                if(l == r){
                    mx[rt] = mn[rt] = a[l];
                    dif[rt] = mx[rt] - mn[rt];
                    return;
                }

                int mid = (l + r) >> 1;
                build(l, mid, rt<<1);
                build(mid+1, r, rt<<1|1);
                pushup(rt);
            }
            vector<int>tmp,res;
            void pushdown(int rt){
                if(lazy[rt] == 0) return;
                lazy[rt<<1] += lazy[rt];
                lazy[rt<<1|1] += lazy[rt];
                mn[rt<<1] += lazy[rt];
                mn[rt<<1|1] += lazy[rt];
                mx[rt<<1] += lazy[rt];
                mx[rt<<1|1] += lazy[rt];
                lazy[rt] = 0;
                return;
            }
            void update(int L, int R ,int c,int l,int r,int rt){
                if(l>=L && r<=R){
                    mx[rt] += c;
                    mn[rt] += c;
                    lazy[rt] += c;
                    return;
                }
                pushdown(rt);
                int mid = (l + r) >> 1;
                if(mid >= L)update(L,R,c,l,mid,rt<<1);
                if(mid < R)update(L,R,c,mid+1,r,rt<<1|1);
                pushup(rt);
            }


int main(){
            int n,m;
            scanf("%d%d", &n, &m);
            for(int i=1; i<=n; i++) scanf("%d", &a[i]);
            build(1,n,1);

            for(int i=1; i<=m; i++) scanf("%d%d", &e[i].fi, &e[i].se);

            int ans = 0;

            for(int i=1; i<=n; i++){

                tmp.clear();

                for(int j=1; j<=m; j++){
                    if(e[j].fi == i){
                        update(e[j].fi,e[j].se,-1,1,n,1);
                    }
                    else if(e[j].se == i-1){
                        update(e[j].fi,e[j].se,1,1,n,1);
                    }
                    if(e[j].fi <=i && e[j].se >= i)
                        tmp.pb(j);
                }
                int q = dif[1];
                if(ans < q){
                    ans = q;
                  //  res.clear();
                    res = tmp;
                    
                }

            }

            printf("%d\n", ans);
            printf("%d\n", (int)res.size());

            for(int i=0; i<(int)res.size(); i++){
                printf("%d ", res[i]);
            }
            puts("");
            return 0;
}
View Code

 

posted @ 2019-01-24 21:09  ckxkexing  阅读(124)  评论(0编辑  收藏  举报