题意: 给定序列, 每次询问一个区间[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)); } }
原文地址:https://www.cnblogs.com/uid001/p/10217674.html
时间: 2024-10-02 00:18:38