标签:ons 权值线段树 线段 老师 update src 情况 ref print
这道题目在\(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;
}
考试时犯的错误:
标签:ons 权值线段树 线段 老师 update src 情况 ref print
原文地址:https://www.cnblogs.com/last-diary/p/11408057.html