# Problem

5 4 5
1 3
2 2
3 1
4 4
2 5
3 5
4 5
2 1
3 1

YES
NO
YES
YES
NO

7 5 4
2 2
3 3
4 2
5 3
6 6
2 1
3 4
3 7
4 5

YES
YES
NO
NO

## Explanation

### Range

1 $$\le 1000$$ $$\le 1000$$
2 $$\le 1000$$ $$\le 1000$$
3 $$\le 10^5$$ $$\le 10^5$$ $$y \le x$$ 恒成立
4 $$\le 10^5$$ $$\le 10^5$$ $$y \le x$$ 恒成立
5 $$\le 10^5$$ $$\le 10^5$$
6 $$\le 10^5$$ $$\le 10^5$$
7 $$\le 10^6$$ $$\le 10^6$$ $$y \le x$$ 恒成立
8 $$\le 10^6$$ $$\le 10^6$$ $$y \le x$$ 恒成立
9 $$\le 10^6$$ $$\le 10^6$$
10 $$\le 10^6$$ $$\le 10^6$$

# Mentality

• 暴力拓展左右端点，复杂度 $$O(n^2)$$$$20pts$$
• 对于所有 $$y\le x$$ 的点用单调栈，$$40pts$$

bool pd(int x)
{
return key[r[x]]>=l[x]&&key[r[x]]<=r[x];
}
for(int i=n;i>=1;i--)
{
stack[++top]=r[i];//r[i]为初始区间右端点
while(pd(i))//如果当前区间右端点的钥匙在区间内
r[i]=stack[--top];//更新右端点并栈内合并区间
}

$$40pts$$ 解决了，那 $$100$$ 分呢？

bool pd(int x)
{
update_l(x);
return key[r[x]]>=l[x]&&key[r[x]]<=r[x];
}
for(int i=n;i>=1;i--)
{
stack[++top]=r[i];
while(pd(i))
r[i]=stack[--top];
}

# Code

#include <cstdio>
#include <iostream>
using namespace std;
#define ls (o << 1)
#define rs ((o << 1) + 1)
#define mid ((l + r) >> 1)
int n, m, Q, key[1000001], ll[1000001], rr[1000001], l[1000001], r[1000001];
int now, top, stack[1000001];
int L, R, X, ans, maxx[4000001];
void build(int o, int l, int r) {
if (l == r) {
maxx[o] = key[l];
return;
}
build(ls, l, mid), build(rs, mid + 1, r);
maxx[o] = max(maxx[ls], maxx[rs]);
}
void query(int o, int l, int r) {
if (ans) return;
if (l == r) {
ans = l;
return;
}
if (mid < R && maxx[rs] > X) query(rs, mid + 1, r);  //显然先找右区间哇
if (mid >= L && maxx[ls] > X) query(ls, l, mid);
}
bool pd(int x) {
L = ll[x], R = l[x] - 1, X = r[x], ans = 0;
query(1, 1, n);
l[x] = !ans ? ll[x] : ans + 1;  //更新左端点
return key[r[x]] >= l[x] && key[r[x]] <= r[x];
}
int main() {
freopen("4436.in", "r", stdin);
freopen("4436.out", "w", stdout);
cin >> n >> m >> Q;
int x, t, now, tp;
for (int i = 1; i <= m; i++) scanf("%d", &x), scanf("%d", &key[x]);
now = 1, tp = 1;
for (int i = 1; i <= n; i++) {
if (key[i - 1]) {
now = i;
if (key[i - 1] < i) tp = i;
}
ll[i] = tp, l[i] = now;
}
now = n, tp = n;
for (int i = n; i >= 1; i--) {
if (key[i]) {
now = i;
if (key[i] > i) tp = i;
}
rr[i] = tp, r[i] = now;
}                //处理出 l，r，ll，rr
build(1, 1, n);  //建树
stack[++top] = n;
for (int i = n; i >= 1; i--) {
stack[++top] = r[i];
while (pd(i)) r[i] = stack[--top];
}  //求出 l，r
while (Q--) {
scanf("%d%d", &x, &t);
printf(t >= l[x] && t <= r[x] ? "YES\n" : "NO\n");
}
}

posted @ 2019-03-11 13:40  洛水·锦依卫  阅读(182)  评论(0编辑  收藏  举报