noi.ac 257 B

链接

题目

  区间[l,r]是连续满足,[l,r]中的数字的权值区间是一段连续的。多次询问可以完包含一个区间的连续区间。区间长度尽量小,如果有多个输出左端点靠左的。

分析:

  [l,r]区间是连续的,当且仅当区间内有(r-l)*2个相邻的关系,即(2,3),(6,5)都是相邻关系。那么将询问离线,不断维护左端点到当前点的区间内的相邻关系的数量。

  即当前点是i,那么如果pos[a[i]-1]<=i的话,在1~pos[a[i]-1]这些位置+1,表示从这些位置到i的区间,增加一个相邻关系。

  如果一个点j开始到i的相邻关系的数量等于(i-j),那么说明(j~i)区间是连续区间,这里两个相邻关系只算了一个。所以初始时在每个位置增加数字下标即可。

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
#include<cctype>
#include<set>
#include<queue>
#include<vector>
#include<map>
#define pa pair<int,int>
using namespace std;
typedef long long LL;

inline LL read() {
    LL x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
    for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
}

const int N = 100005;
pa T[N << 2];
int tag[N << 2], pos[N], a[N], ans1[N], ans2[N], n;
set< pa > s;
vector< pa > q[N];

pa operator + (pa A, pa B) { return A.first > B.first ? A : B; }

inline void col(int x,int y) { T[x].first += y, tag[x] += y; }
inline void pushdown(int rt) { col(rt << 1, tag[rt]); col(rt << 1 | 1, tag[rt]); tag[rt] = 0; }

void build(int l,int r,int rt) {
    if (l == r) { T[rt] = pa(l, l); return ; }
    int mid = (l + r) >> 1;
    build(l, mid, rt << 1); build(mid + 1, r, rt << 1 | 1);
    T[rt] = T[rt << 1] + T[rt << 1 | 1];
}
void update(int l,int r,int rt,int L,int R) {
    
    if (L <= l && r <= R) { T[rt].first ++, tag[rt] ++; return ; }
    int mid = (l + r) >> 1;
    if (tag[rt]) pushdown(rt);
    if (L <= mid) update(l, mid, rt << 1, L, R);
    if (R > mid) update(mid + 1, r, rt << 1 | 1, L, R);
    T[rt] = T[rt << 1] + T[rt << 1 | 1];
}
pa query(int l,int r,int rt,int L,int R) {
    if (L <= l && r <= R) return T[rt];
    if (tag[rt]) pushdown(rt);
    int mid = (l + r) >> 1;
    if (R <= mid) return query(l, mid, rt << 1, L, R);
    else if (L > mid) return query(mid + 1, r, rt << 1 | 1, L, R);
    else return query(l, mid, rt << 1, L, R) + query(mid + 1, r, rt << 1 | 1, L, R);
}
bool check(pa x,int i) {
    pa now = query(1, n, 1, 1, -x.first);
    if (now.first == i) {
        ans1[x.second] = now.second, ans2[x.second] = i;
        return 1;
    }
    return 0;
}
int main() {
    n = read();
    for (int i = 1; i <= n; ++i) a[i] = read(), pos[a[i]] = i;
    int m = read();
    for (int i = 1; i <= m; ++i) {
        int l = read(), r = read(); q[r].push_back(pa(-l, i));
    }
    build(1, n, 1);
    for (int i = 1; i <= n; ++i) {
        for (int j = 0; j < (int)q[i].size(); ++j) s.insert(q[i][j]);
        if (a[i] > 1 && pos[a[i] - 1] <= i) update(1, n, 1, 1, pos[a[i] - 1]);
        if (a[i] < n && pos[a[i] + 1] <= i) update(1, n, 1, 1, pos[a[i] + 1]);
        while (!s.empty()) 
            if (check(*s.begin(), i)) s.erase(s.begin());
            else break;
    }
    for (int i = 1; i <= m; ++i) printf("%d %d
", ans1[i], ans2[i]);
    return 0;
}
原文地址:https://www.cnblogs.com/mjtcn/p/10549149.html