noi.ac 257 B

时间:2023-03-09 18:51:37
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=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
} const int N = ;
pa T[N << ];
int tag[N << ], 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 << , tag[rt]); col(rt << | , tag[rt]); tag[rt] = ; } void build(int l,int r,int rt) {
if (l == r) { T[rt] = pa(l, l); return ; }
int mid = (l + r) >> ;
build(l, mid, rt << ); build(mid + , r, rt << | );
T[rt] = T[rt << ] + T[rt << | ];
}
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) >> ;
if (tag[rt]) pushdown(rt);
if (L <= mid) update(l, mid, rt << , L, R);
if (R > mid) update(mid + , r, rt << | , L, R);
T[rt] = T[rt << ] + T[rt << | ];
}
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) >> ;
if (R <= mid) return query(l, mid, rt << , L, R);
else if (L > mid) return query(mid + , r, rt << | , L, R);
else return query(l, mid, rt << , L, R) + query(mid + , r, rt << | , L, R);
}
bool check(pa x,int i) {
pa now = query(, n, , , -x.first);
if (now.first == i) {
ans1[x.second] = now.second, ans2[x.second] = i;
return ;
}
return ;
}
int main() {
n = read();
for (int i = ; i <= n; ++i) a[i] = read(), pos[a[i]] = i;
int m = read();
for (int i = ; i <= m; ++i) {
int l = read(), r = read(); q[r].push_back(pa(-l, i));
}
build(, n, );
for (int i = ; i <= n; ++i) {
for (int j = ; j < (int)q[i].size(); ++j) s.insert(q[i][j]);
if (a[i] > && pos[a[i] - ] <= i) update(, n, , , pos[a[i] - ]);
if (a[i] < n && pos[a[i] + ] <= i) update(, n, , , pos[a[i] + ]);
while (!s.empty())
if (check(*s.begin(), i)) s.erase(s.begin());
else break;
}
for (int i = ; i <= m; ++i) printf("%d %d\n", ans1[i], ans2[i]);
return ;
}