noi.ac day6t3 color
阿新 • • 發佈:2018-11-09
分析
將詢問離線,列舉右端點。新加入一個右端點i時,假設離i第t近的同色位置為p,t+1近的是q,則當i是右端點時,(q,p]的點可以作為左端點。
注意對於一個點離它第t近的同色點可以用佇列維護求得
之後用樹狀陣列差分一下就可以了
程式碼
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include <algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
struct node {
int le,ri,id;
};
node a[500010];
vector<int>q[500010 ];
int C[500010],d[500010],n,m,k,t,ans[500010];
int nxt[500010],fa[500010],pre[500010],ppre[500010],is[500010];
inline bool cmp(const node x,const node y){return x.ri<y.ri;}
inline int lb(int x){return x&(-x);}
inline void add(int x,int k){while(x<=n)d[x]+=k,x+=lb(x);}
inline int Q(int x){int res=0;while(x)res+=d[x],x-=lb(x);return res;}
int main(){
int i,j=1;
scanf("%d%d%d%d",&n,&m,&k,&t);
for(i=1;i<=n;i++)scanf("%d",&C[i]);
for(i=1;i<=m;i++)scanf("%d%d",&a[i].le,&a[i].ri),a[i].id=i;
sort(a+1,a+m+1,cmp);
for(i=1;i<=k;i++)q[i].push_back(0);
for(i=1;i<=n;i++){
int x=C[i],s=q[x].size();
q[x].push_back(i);
if(s>=t)add(q[x][s-t]+1,1),add(q[x][s-t+1]+1,-1);
if(s>t)add(q[x][s-t-1]+1,-1),add(q[x][s-t]+1,1);
for(j;j<=m;j++)
if(a[j].ri==i)ans[a[j].id]=Q(a[j].le);
else break;
}
for(i=1;i<=m;i++)printf("%d\n",ans[i]);
return 0;
}