NOI-Online 2022 提高组

被单调队列了。

T1 P8251 丹钓战

思路

单调栈预处理出一个 $c$ 数组以记录每一个数对答案的贡献。然后将题意转化为求 $[l,r]$ 中小于 $l$ 的个数,每个元素对答案的贡献当且仅当其下的元素不在 $[l,r]$ 之间。用主席树维护即可。

官方时间复杂度 $O((n+q) \log n)$

考场没打出来,暴力30pt

AC Code

查看代码
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<ctime>
#include<iomanip>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#define gh() getchar()
#define re register
#define underMax(x,y) ((x)>(y)?(x):(y))
#define underMin(x,y) ((x)<(y)?(x):(y))
typedef long long ll;
using namespace std;
const int MAXN=5e5+1;
const int INF=1e9;
template<class T>
inline void underRead(T &x)
{
x=0;
char ch=gh(),t=0;
while(ch<'0'||ch>'9') t|=ch=='-',ch=gh();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=gh();
if(t) x=-x;
}
int N,M,T,Rt[MAXN],Idx,Ql,Qr;
int a[MAXN],b[MAXN],c[MAXN];
struct PST
{
int l,r,dat;
}Tree[MAXN<<6];
inline void underPushUp(int x)
{
Tree[x].dat=Tree[Tree[x].l].dat+Tree[Tree[x].r].dat;
}
inline void underBuild(int &x,int l,int r)
{
x=++Idx;
if(l==r) return ;
int mid=(l+r)>>1;
underBuild(Tree[x].l,l,mid),underBuild(Tree[x].r,mid+1,r);
}
inline void underModify(int &x,int l,int r,int d)
{
Tree[++Idx]=Tree[x];
++Tree[Idx].dat,x=Idx;
if(l==r) return ;
int mid=(l+r)>>1;
if(d<=mid) underModify(Tree[x].l,l,mid,d);
else underModify(Tree[x].r,mid+1,r,d);
}
inline int underQuery(int x,int l,int r,int k)
{
if(l==r) return 0;
int mid=(l+r)>>1;
if(k==mid) return Tree[Tree[x].l].dat;
if(k<mid) return underQuery(Tree[x].l,l,mid,k);
return Tree[Tree[x].l].dat+underQuery(Tree[x].r,mid+1,r,k);
}
int main()
{
// freopen("stack.in","r",stdin);
// freopen("stack.out","w",stdout);
underRead(N),underRead(M);
for(re int i=1;i<=N;++i) underRead(a[i]);
for(re int i=1;i<=N;++i) underRead(b[i]);
a[0]=c[0]=0;
b[0]=INF;
underBuild(Rt[0],0,N);
for(int i=1;i<=N;++i)
{
int l=0,r=T,mid;
while(l<r)
{
mid=(l+r+1)>>1;
if(b[i]<b[c[mid]]) l=mid;
else r=mid-1;
}
while(a[c[l]]==a[i]) --l;
T=l+1;
c[T]=i;
Rt[i]=Rt[i-1];
underModify(Rt[i],0,N,c[l]);
}
for(re int i=1;i<=M;++i)
{
underRead(Ql),underRead(Qr);
printf("%d\n",underQuery(Rt[Qr],0,N,Ql-1)-underQuery(Rt[Ql-1],0,N,Ql-1));
}
return 0;
}
/*
10 4
3 1 3 1 2 3 3 2 1 1
10 10 2 9 7 5 4 7 6 1
1 4
7 8
7 10
1 8
*/

T2 P8252 讨论

T3 P8253 如何正确地排序