题目链接:https://ac.nowcoder.com/acm/contest/9033/D
思路:预处理出区间右边界为i时,左边界的可取范围[ l[i],r[i] ]。具体就是用队列来存储值为a[i]的下标,先把i放入队列中。如果队列里的下标大于k个,那么,l[i] 为q.front()+1与 l[i-1](区间要满足第i-1的值的区间)的较大值,并且队首出列。如果,队列里的下标等于k个,r[i] 为q.front()与 r[i-1]的较大值。对询问区间的右端点从小到达排序,线段树维护当前询问所有可取的区间的左端点的个数,区间更新,区间查询。
#include <bits/stdc++.h>
#define ll long long
#define lson (cur<<1)
#define rson (cur<<1|1)
using namespace std;
const int N = 3e5+10;
int n,m,k,a[N],l[N],r[N];
queue<int> qu[N];
struct Node{
int id,l,r;
bool operator <(const Node & a){
return r<a.r;
}
}q[N];
struct node{
int l,r,lazy;
ll sum;
}tree[N<<2];
ll ans[N];
void build(int cur,int l,int r){
tree[cur].l=l,tree[cur].r=r;
if(l==r) return;
int m=(l+r)>>1;
build(lson,l,m);
build(rson,m+1,r);
}
void pushdown(int cur){
if(tree[cur].lazy){
tree[lson].lazy+=tree[cur].lazy,tree[rson].lazy+=tree[cur].lazy;
tree[lson].sum+=1LL*(tree[lson].r-tree[lson].l+1)*tree[cur].lazy;
tree[rson].sum+=1LL*(tree[rson].r-tree[rson].l+1)*tree[cur].lazy;
tree[cur].lazy=0;
}
}
void pushup(int cur){
tree[cur].sum=tree[lson].sum+tree[rson].sum;
}
void update(int cur,int pl,int pr){
if(pl<=tree[cur].l&&tree[cur].r<=pr){
tree[cur].lazy++;
tree[cur].sum+=1LL*(tree[cur].r-tree[cur].l+1);
return ;
}
pushdown(cur);
if(pl<=tree[lson].r) update(lson,pl,pr);
if(pr>=tree[rson].l) update(rson,pl,pr);
pushup(cur);
}
ll query(int cur,int pl,int pr){
if(pl<=tree[cur].l&&tree[cur].r<=pr){
return tree[cur].sum;
}
pushdown(cur);
ll res=0;
if(pl<=tree[lson].r) res+=query(lson,pl,pr);
if(pr>=tree[rson].l) res+=query(rson,pl,pr);
return res;
pushup(cur);
}
int main(void){
scanf("%d%d%d",&n,&m,&k);
l[0]=1;
for(int i=1;i<=n;i++){
l[i]=l[i-1],r[i]=r[i-1];
scanf("%d",&a[i]);
qu[a[i]].push(i);
int siz=qu[a[i]].size();
if(siz>k){
l[i]=max(l[i],qu[a[i]].front()+1);
qu[a[i]].pop(),siz--;
}
if(siz==k)
r[i]=max(r[i],qu[a[i]].front());
}
for(int i=1;i<=m;i++){
scanf("%d%d",&q[i].l,&q[i].r);
q[i].id=i;
}
sort(q+1,q+1+m);
build(1,1,n);
int pos=1;
for(int i=1;i<=m;i++){
while(pos<=q[i].r){
if(r[pos]) update(1,l[pos],r[pos]);
pos++;
}
ans[q[i].id]=query(1,q[i].l,q[i].r);
}
for(int i=1;i<=m;i++)
printf("%lld\n",ans[i]);
return 0;
}