NOI Online 2022 T1 丹掉战 总结
written on 2022-03-26
通过这道题,我对查询一段区间内小于给定值的数的个数这样的题型有了较好的认识
比赛的时候,其实已经想到了要处理出每一个位置,它的前一个需要依存的数的位置,这个用单调栈直接模拟即可,是 \(O(n)\) 的,然后对于每一个区间,看看比 \(l\) 小的数有几个
那么现在给出这个操作的代码,其实就是离线预处理后,用树状数组来进行前缀的查询
P1972 HH的项链 是类似的思路
#include<bits/stdc++.h>
#define N 500005
using namespace std;
int n,q,a[N],b[N];
int top,p[N],ans[N];
struct f{int l,r,id;}t[N];
struct g{int num,id;}to[N];
bool cmp1(f a,f b){return a.l<b.l;}
bool cmp2(g a,g b){return a.num<b.num;}
struct Fenwick
{
int c[N];
void add(int x,int v){for(;x<=n;x+=x&-x) c[x]+=v;}
int ask(int x)
{
int res=0;
for(;x;x-=x&-x) res+=c[x];
return res;
}
}t1;
int main()
{
// freopen("stack.in","r",stdin);
// freopen("stack.out","w",stdout);
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++) scanf("%d",&b[i]);
for(int i=1;i<=n;i++)
{
while(top&&(a[p[top]]==a[i]||b[p[top]]<=b[i])) top--;
to[i].num=p[top],to[i].id=i;
p[++top]=i;
}
// for(int i=1;i<=n;i++) printf("%d ",to[i]);
sort(to+1,to+1+n,cmp2);
for(int i=1;i<=q;i++) scanf("%d%d",&t[i].l,&t[i].r),t[i].id=i;
sort(t+1,t+1+q,cmp1);
int pos=1;
for(int i=1;i<=q;i++)
{
while(pos<=n&&to[pos].num<t[i].l)
{
t1.add(to[pos].id,1);
pos++;
}
ans[t[i].id]=t1.ask(t[i].r)-t1.ask(t[i].l-1);
}
for(int i=1;i<=q;i++) printf("%d\n",ans[i]);
return 0;
}
update on 2022-7-31
其实也可以直接用主席树维护的/dk
现在看起来真的好简单啊