https://ac.nowcoder.com/acm/contest/84527/C
题意:
给一个长度为 n 的正整数数组 a,一个长度为 m 的查询数组 q,q[i]=(val,minlen,maxlen)。请你按输入顺序处理这 m 次查询,对于第 i 次查询q[i]=(val,minlen,maxlen):请你输出是否存在一个 a 的子数组 s 满足 min(s)≥val 且 s 的长度在 minlen 和 maxlen 之间。
struct sb
{
int val, id;
}a[N];
int l[N], r[N], ans[N];
int main()
{
int n; cin >> n;
for(int i = 1; i <= n; i ++)
cin >> a[i].val, a[i].id = i;
stack<sb>s, q;
s.push({0, 0});
for(int i = 1; i <= n; i ++)//找左边第一个小于该值的位置
{
while(s.top().val >= a[i].val) s.pop();
l[i] = i - s.top().id - 1; //存这中间有多少个数
s.push({a[i].val, i});
}
q.push({0, n + 1});
for(int i = n; i > 0; i --)//找右边的
{
while(q.top().val >= a[i].val) q.pop();
r[i] = q.top().id - i - 1;
q.push({a[i].val, i});
}
//这一步是找长度为t的最大值
for(int i = 1; i <= n; i ++)
{
int t = l[i] + r[i] + 1;
ans[t] = max(ans[t], a[i].val);
}
//以防有些长度算不上, 所以这里是将其往大处找
//如1 3 2 4 5,r[2]就会=0
//也是为了下面的可以直接用minlen来判断
for(int i = n; i > 0; i --)
ans[i] = max(ans[i], ans[i + 1]);
int m; cin >> m;
while(m --)
{
int x, y, z; cin >> x >> y >> z;
//以最小的算即可, 因为我们存的都是被允许的范围内的最大值
if(ans[y] >= x) cout << "Yes" << endl;
else cout << "No" << endl;
}
return 0;
}