Codeforces 813E Army Creation [主席树]

本文介绍了一种使用主席树解决区间内元素计数问题的方法。通过构建主席树并结合差分思想,可以有效地处理区间内相同数字最多选择k个的情况。文章提供了详细的AC代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:给你长度为n的序列,有q个询问,询问[l,r]区间内相同数字最多选k个的总个数。

题解:建立关于位置的主席树,利用差分的思想,对于新加入的一个数,当前位置+1,并在之前第i-k个位置-1,最后询问root[r]中区间[l,r]的总和。

AC代码:

#include<stdio.h>  
#include<vector>  
#include<algorithm>  
#define N 100005  
using namespace std;  
vector<int>vt[N];  
int tree[N*36],lchild[N*36],rchild[N*36],root[N],tot;  
void insert(int last,int cur,int x,int L,int R,int k)  
{  
    tree[cur]=tree[last]+k;  
    lchild[cur]=lchild[last];  
    rchild[cur]=rchild[last];  
    if(L==R)return ;  
    int mid=L+R>>1;  
    if(x<=mid)insert(lchild[last],lchild[cur]=++tot,x,L,mid,k);  
    else insert(rchild[last],rchild[cur]=++tot,x,mid+1,R,k);  
}  
int query(int l,int r,int L,int R,int root)  
{  
    if(l<=L&&R<=r)return tree[root];  
    int mid=L+R>>1;  
    if(r<=mid)return query(l,r,L,mid,lchild[root]);  
    else if(l>mid)return query(l,r,mid+1,R,rchild[root]);  
    else return query(l,mid,L,mid,lchild[root])+query(mid+1,r,mid+1,R,rchild[root]);  
}  
int main()  
{  
    int n,k,q,x;  
    scanf("%d%d",&n,&k);  
    for(int i=1;i<=n;i++)  
    {  
        scanf("%d",&x);  
        vt[x].push_back(i);  
        insert(root[i-1],root[i]=++tot,i,1,n,1);  
        if(vt[x].size()>k)
		{
			int now=++tot;
			insert(root[i],now,vt[x][vt[x].size()-k-1],1,n,-1);
			root[i]=now;  
		}
    }  
    int last=0;  
    scanf("%d",&q);  
    while(q--)  
    {  
        int l,r;  
        scanf("%d%d",&l,&r);  
        l=(l+last)%n+1;  
        r=(r+last)%n+1;  
        if(l>r)swap(l,r);  
        last=query(l,r,1,n,root[r]);  
        printf("%d\n",last);  
    }  
}  




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值