• CF813E-Army Creation【主席树】


    题意:

    给定 (N) 个数,以及 (Q) 个询问,每个询问给出 (L)(R),现在问在这个区间最多可以选取多少个数,使得每个数出现次数不能大于 (K),强制在线。

    分析:

      当 (k=1) 时,本题就是求区间内不同的数的个数。因此,二者可以采用相同的方法来解决。
      在求区间内不同数的个数的问题中,以位置建立主席树,记录每个数上一次出现的位置,当该数再次出现时,消除前一次出现的影响,记录这一次的影响。
      本题中,用数组记录每个数最近 (k) 次出现的位置,当第 (k+1) 次出现时,把第 (1) 次出现的影响消除,记录下第 (k+1) 次的影响,以此类推。

    代码:

    #include <bits/stdc++.h>
    #define pb push_back
    using namespace std;
    const int N=1e5+5;
    struct node
    {
        int val,lson,rson;
    }tree[N*40];
    int root[N],tol;
    vector<int>ap[N];
    void pushup(int t)
    {
        tree[t].val=tree[tree[t].lson].val+tree[tree[t].rson].val;
    }
    int build(int l,int r)
    {
        int cnt=++tol;
        if(l==r)
        {
            tree[cnt].val=0;
            return cnt;
        }
        int mid=(l+r)>>1;
        tree[cnt].lson=build(l,mid);
        tree[cnt].rson=build(mid+1,r);
        pushup(cnt);
        return cnt;
    }
    int update(int l,int r,int pos,int w,int rt)
    {
        int cnt=++tol;
        tree[cnt]=tree[rt];
        if(l==r)
        {
            tree[cnt].val+=w;
            return cnt;
        }
        int mid=(l+r)>>1;
        if(pos<=mid)
            tree[cnt].lson=update(l,mid,pos,w,tree[rt].lson);
        else
            tree[cnt].rson=update(mid+1,r,pos,w,tree[rt].rson);
        pushup(cnt);
        return cnt;
    }
    int query(int l,int r,int L,int R,int rt)
    {
        if(L<=l&&r<=R)
            return tree[rt].val;
        int mid=(l+r)>>1,res=0;
        if(L<=mid)
            res+=query(l,mid,L,R,tree[rt].lson);
        if(R>mid)
            res+=query(mid+1,r,L,R,tree[rt].rson);
        return res;
    }
    int main()
    {
        int n,k,a,q,x,y,l,r,ans=0;
        tol=0;
        scanf("%d%d",&n,&k);
        root[0]=build(1,n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a);
            ap[a].pb(i);
            if(ap[a].size()>k)
            {
                root[i]=update(1,n,ap[a][0],-1,root[i-1]);
                root[i]=update(1,n,i,1,root[i]);
                ap[a].erase(ap[a].begin());
            }
            else
                root[i]=update(1,n,i,1,root[i-1]);
        }
        scanf("%d",&q);
        while(q--)
        {
            scanf("%d%d",&x,&y);
            l=(x+ans)%n+1;
            r=(y+ans)%n+1;
            if(l>r) swap(l,r);
            ans=query(1,n,l,r,root[r]);
            printf("%d
    ",ans);
        }
        return 0;
    }
    
    
  • 相关阅读:
    Linux C多线程实现生产者消费者
    数据库视图创建学习
    jsp生成好看的验证码
    每日英语
    ES6学习笔记(一)——let和const
    dataTables的导出Excel功能
    jquery生成二维码图片
    angular2表单初体验
    echarts系列之动态加载数据
    js刷新页面方法
  • 原文地址:https://www.cnblogs.com/1024-xzx/p/13205381.html
Copyright © 2020-2023  润新知