Army Creation CodeForces - 813E (水题)

题意: 给定序列, 每次询问一个区间[l,r], 问[l,r]中最多能选多少个数且每种数字不超过k

相当于加强版 HH的项链, 对于一个数t, 主席树维护上k次出现的位置pre[t], 每次查询相当于求区间内pre<左端点的总数

#include <iostream>
#include <queue>
#define REP(i,a,n) for(int i=a;i<=n;++i)
#define mid ((l+r)>>1)
using namespace std;
const int N = 1e5+10, INF = 0x3f3f3f3f;
int tot, n, m, k;
int cnt[N], rt[N];
deque<int> pre[N];

struct _ {int l,r,sum;} tr[N<<5];

void ins(int &o, int l, int r, int x) {
    ++tot,tr[tot]=tr[o],o=tot,++tr[o].sum;
    if (l==r) return;
    if (mid>=x) ins(tr[o].l,l,mid,x);
    else ins(tr[o].r,mid+1,r,x);
}

int query(int u, int v, int l, int r, int x) {
    if (l==r) return 0;
    if (mid>=x) return query(tr[u].l,tr[v].l,l,mid,x);
    return tr[tr[v].l].sum-tr[tr[u].l].sum+query(tr[u].r,tr[v].r,mid+1,r,x);
}

int main() {
    scanf("%d%d", &n, &k);
    REP(i,1,n) {
        int t, x=0;
        scanf("%d", &t); rt[i] = rt[i-1];
        if (pre[t].size()==k) { 
            x = pre[t].front();
            pre[t].pop_front();
        }
        ins(rt[i],0,n,x);
        pre[t].push_back(i);
    }
    scanf("%d", &m);
    int ans = 0;
    REP(i,1,m) {
        int l, r;
        scanf("%d%d", &l, &r);
        l = (l+ans)%n+1;
        r = (r+ans)%n+1;
        if (l>r) swap(l,r);
        printf("%d\n", ans=query(rt[l-1],rt[r],0,n,l));
    }
}

猜你喜欢

转载自www.cnblogs.com/uid001/p/10217674.html