Educational Codeforces Round 22E

给你n和k,n个数,每个数范围1e5,m次查询,每次查询区间(l,r),在区间中的每个数,如果超过k次只算k次,否则算原来的次数,求总次数,强制在线

解法:线段树维护区间中每个数经过k次到达的点pos,然后其中pos<=r的就是能满足条件的加到答案上即可

因为假设原来的点是x(l<=x<=r),经过k次是pos(l<=pos<=r),那么此时我们不能同时算这两个点的贡献,所以只需要算后一个点的贡献,当pos的经过k次到达的点也<=r时,那么pos点也不能算进来,以此类推

线段树每个区间维护一个vector,vector要sort一下,然后查询lowerbound,复杂度O(nlognlogn)

//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pii pair<int,int>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0)

using namespace std;

const double g=10.0,eps=1e-9;
const int N=2000000+10,maxn=100000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;

int a[maxn],ans[maxn],num[maxn];
int Next[maxn],id[maxn];
vector<int>v[N];
void pushup(int rt)
{
    v[rt].clear();
//    v[rt].resize(v[rt<<1].size()+v[rt<<1|1].size());
    for(int i=0;i<v[rt<<1].size();i++)
        v[rt].pb(v[rt<<1][i]);
    for(int i=0;i<v[rt<<1|1].size();i++)
        v[rt].pb(v[rt<<1|1][i]);
    sort(v[rt].begin(),v[rt].end());
}
void build(int l,int r,int rt)
{
    if(l==r)
    {
        v[rt].pb(ans[l]);
        return ;
    }
    int m=(l+r)>>1;
    build(ls);build(rs);
    pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
//        for(int i=0;i<v[rt].size();i++)
//            printf("%d ",v[rt][i]);
        int p=upper_bound(v[rt].begin(),v[rt].end(),R)-v[rt].begin();
        return p;
    }
    int m=(l+r)>>1,ans=0;
    if(L<=m)ans+=query(L,R,ls);
    if(m<R)ans+=query(L,R,rs);
    return ans;
}
int main()
{
    int n,k;
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        ans[i]=id[i]=n+1;
    }
    for(int i=n;i>=1;i--)
    {
        Next[i]=id[a[i]];
        id[a[i]]=i;
    }
    memset(id,0,sizeof id);
    for(int i=n;i>=1;i--)id[a[i]]=i;
    for(int i=1;i<=n;i++)
    {
        if(num[a[i]]==k)
        {
            ans[id[a[i]]]=i;
            id[a[i]]=Next[id[a[i]]];
        }
        else num[a[i]]++;
    }
//    for(int i=1;i<=n;i++)
//        printf("%d ",ans[i]);
//    puts("");
    build(1,n,1);
//    printf("%d
",2-1+1-query(1,2,1,n,1));
    int q,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=r-l+1-query(l,r,1,n,1);
        printf("%d
",last);
    }
    return 0;
}
/********************

********************/
View Code
原文地址:https://www.cnblogs.com/acjiumeng/p/8515449.html