page
Posted last-diary
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了page相关的知识,希望对你有一定的参考价值。
page
这道题目在\(luogu\)上有原题--P3419 [POI2005]SAM-Toy Cars。
这道题在\(ZR\)时候老师讲过,但是当时讲的是堆做法,比较麻烦,也没有写出来,所以考试的时候写的是权值线段树的做法。
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
const int N=2e5+100;
struct Tree
int ls,rs,sum;
t[N<<1];
deque<int>q[N];
int n,k,ans,cnt=1;
int a[N],tp[N];
bool mark[N];
inline void push_up(int rt)
t[rt].sum=t[t[rt].ls].sum+t[t[rt].rs].sum;
return ;
inline int query(int rt,int l,int r,int k)
if (l==r)
return l;
int sz=t[t[rt].ls].sum,mid=(l+r)>>1;
if (k<=sz) return query(t[rt].ls,l,mid,k);
else return query(t[rt].rs,mid+1,r,k-sz);
inline void update(int rt,int l,int r,int opt,int x)
if (l==r)
if (opt==1) t[rt].sum++;
if (opt==2&&t[rt].sum) t[rt].sum--;
return ;
int mid=(l+r)>>1;
if (x<=mid) update(t[rt].ls,l,mid,opt,x);
else update(t[rt].rs,mid+1,r,opt,x);
push_up(rt);
return ;
inline void build(int rt,int l,int r)
if (l==r)
t[rt].sum=0;
return ;
int mid=(l+r)>>1;
t[rt].ls=++cnt;
build(t[rt].ls,l,mid);
t[rt].rs=++cnt;
build(t[rt].rs,mid+1,r);
return ;
int main()
freopen("page.in","r",stdin);
freopen("page.out","w",stdout);
int maxx=0;
scanf("%d%d",&n,&k);
for (int i=1;i<=n;i++)
scanf("%d",a+i);
q[a[i]].push_back(i);
maxx=max(a[i],maxx);
build(1,1,n+1);
for (int i=1;i<=maxx;i++)
q[i].push_back(n+1);
for (int i=1;i<=n;i++)
int x=a[i];
if (!mark[x])
if (t[1].sum<k)
while (q[x].front()<=i)
q[x].pop_front();
update(1,1,n+1,1,q[x].front());
tp[q[x].front()]=x;
mark[x]=1;
else
while (q[x].front()<=i&&!q[x].empty())
q[x].pop_front();
int now=query(1,1,n+1,t[1].sum);
update(1,1,n+1,2,now);
mark[tp[now]]=0;
tp[now]=0;
update(1,1,n+1,1,q[x].front());
tp[q[x].front()]=x;
mark[x]=1;
ans++;
else
while (q[x].front()<=i&&!q[x].empty())
update(1,1,n+1,2,q[x].front());
tp[q[x].front()]=0;
q[x].pop_front();
update(1,1,n+1,1,q[x].front());
tp[q[x].front()]=x;
printf("%d\n",ans);
return 0;
考试时犯的错误:
- 最后一种情况双端队列弹反了
- 想错数据范围,认为\(a_i<=n\),所以导致预处理错误,以后预处理就按上面的方法了
以上是关于page的主要内容,如果未能解决你的问题,请参考以下文章