CF1887D Split

Description

https://www.luogu.com.cn/problem/CF1887D

Solution

感觉思路就错了。赛时一直在往整个区间往右边移动的角度想,而没有考虑对分割点算贡献

拿我们就来算贡献吧!假设我们已经确定了一个区间,考虑计算区间每个点是否可能作为区间分割点的左边最大值,也就是对于点 $a_x$ ,能否分为两部分使得左边 $\le a_x$ ,右边 $>a_x$。

如果已经知道了 $<a_x$ 的数的集合。令 $u$ 为 $a_x$ 左边第一个比 $a_x$ 大的数,则左端点的范围为 $u<l\le x$。$v$ 为右边第一个比 $a_x$ 大的数,$k$ 为 $v$ 右边第一个比 $a_x$ 小的数,则右端点的范围为 $u\le r<k$。

然后树状数组+扫描线即可。

要是问我分割点的个数我说不定还能场切

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define maxn 300005
#define put() putchar('\n')
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
using namespace std;
void read(int &x){
int f=1;x=0;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
x*=f;
}
namespace Debug{
Tp void _debug(char* f,Ty t){cerr<<f<<'='<<t<<endl;}
Ts void _debug(char* f,Ty x,Ar... y){while(*f!=',') cerr<<*f++;cerr<<'='<<x<<",";_debug(f+1,y...);}
Tp ostream& operator<<(ostream& os,vector<Ty>& V){os<<"[";for(auto& vv:V) os<<vv<<",";os<<"]";return os;}
#define gdb(...) _debug((char*)#__VA_ARGS__,__VA_ARGS__)
}using namespace Debug;
#define fi first
#define se second
#define mk make_pair
const int mod=1e9+7;
int power(int x,int y=mod-2) {
int sum=1;
while (y) {
if (y&1) sum=sum*x%mod;
x=x*x%mod;y>>=1;
}
return sum;
}
int n,m;
int a[maxn],id[maxn],Ans[maxn];
vector<pair<int,int> >q[maxn];
vector<pair<int,int> >O[maxn];
set<int>tl,tr;
struct BIT {
#define lowbit(x) ((x)&(-(x)))
int f[maxn];
void add(int x,int y) {for (;x<=n;x+=lowbit(x)) f[x]+=y;}
int query(int x) {int sum=0;for (;x;x-=lowbit(x)) sum+=f[x];return sum;}
}t;
signed main(void){
freopen("1.in","r",stdin);
int i,x,y;
read(n);
tr.insert(0);tr.insert(n+1);
tl.insert(0);
for (i=1;i<=n;i++) read(a[i]),id[a[i]]=i,tr.insert(i);
read(m);
for (i=1;i<=m;i++) read(x),read(y),q[x].push_back(mk(y,i));
for (i=1;i<=n;i++) {
x=id[i];
int tmp1=0,tmp2=n+1,tmp3=n+1;
tr.erase(x);
auto it1=tr.lower_bound(x);it1--;tmp1=(*it1)+1;
auto it2=tr.lower_bound(x);
if (it2!=tr.end()) {
tmp2=(*it2);
auto it3=tl.lower_bound(tmp2);
if (it3!=tl.end()) tmp3=(*it3)-1;
}
tl.insert(x);
O[tmp1].push_back(mk(tmp2,1));
O[tmp1].push_back(mk(tmp3+1,-1));
O[x+1].push_back(mk(tmp2,-1));
O[x+1].push_back(mk(tmp3+1,1));
}
for (i=1;i<=n;i++) {
for (auto tmp:O[i]) t.add(tmp.fi,tmp.se);
for (auto tmp:q[i]) Ans[tmp.se]=t.query(tmp.fi);
}
for (i=1;i<=m;i++) puts(Ans[i]?"Yes":"No");
return 0;
}