码迷,mamicode.com
首页 > 其他好文 > 详细

page

时间:2019-08-25 15:53:21      阅读:80      评论:0      收藏:0      [点我收藏+]

标签:ons   权值线段树   线段   老师   update   src   情况   ref   print   

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

标签:ons   权值线段树   线段   老师   update   src   情况   ref   print   

原文地址:https://www.cnblogs.com/last-diary/p/11408057.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!