洛谷P1311
Keywords: #algorithm
#solution
$ O(n) $ 做法
首先预处理一个数组res[i]
,表示第 $ 1 $ 到 $ i $ 的客栈中编号最大且满足最低消费小于等于q的客栈编号;
维护一个前缀和数组ans[i][j]
,i为颜色,j为编号, $ O(1) $ 求出 1~j 中有多少个颜色为i的客栈;
枚举较大的客栈的编号i,1~res[i]
是不考虑颜色因素所能选的区间,ans[i][res[i]]即是右端点为i时的答案.
注意当res[i]=i时,因为一个客栈不能选两次,因此答案要减一.
累加即可.
#include<cstdio>
#include<cstring>
using namespace std;
int n,k,p;
int a[200005],b,res[200005],ans[55][200005];
long long ret=0;
int main(){
memset(res,-1,sizeof res);
scanf("%d%d%d",&n,&k,&p);
for(int i=1;i<=n;i++){
scanf("%d%d",&a[i],&b);
if(b<=p){
res[i]=i;
}
else{
res[i]=res[i-1];
}
}
for(int i=1;i<=n;i++){
for(int type=0;type<=k;type++){
ans[type][i]=ans[type][i-1];
if(a[i]==type){
ans[type][i]++;
}
}
}
for(int i=1;i<=n;i++){
if(i==res[i]){
ret--;
}
ret+=ans[a[i]][res[i]];
}
printf("%lld",ret);
return 0;
}