开始想用分治,找到中间的一个小于的客栈,然后用到它的两边的客栈的贡献就可以用前缀和轻易算出。然后递归处理左右。
后来发现没有这个必要,从左向右扫一遍就好了。
每次找到当前第一个小于的客栈,这样它前面的客栈与他自己的贡献便可以处理。
预处理,主过程
.
#include<iostream>
#include<cstdio>
#define maxn 200010
using namespace std;
int f[maxn][60],v[maxn],col[maxn];
int main(){
int n,k,p;scanf("%d%d%d",&n,&k,&p);
for(int i=1;i<=n;i++)scanf("%d%d",&col[i],&v[i]);
for(int k=0;k<=50;k++)
for(int i=1;i<=n;i++)
f[i][k]=f[i-1][k]+(col[i]==k);
//for(int k=0;k<=1;k++)
//for(int i=1;i<=n;i++)cout<<k<<' '<<i<<' '<<f[i][k]<<endl;
int Ans=0;
for(int i=1,l=0,r=0;i<=n;i++){//cout<<i<<endl;
if(v[i]>p){
if(l==0&&r==0)l=r=i;
else r=i;
//cout<<l<<' '<<r<<endl;
}
if(v[i]<=p){
if(l&&r)
for(int j=l;j<=r;j++)
Ans+=f[n][col[j]]-f[r][col[j]];
Ans+=f[n][col[i]]-f[i][col[i]];
l=r=0;
//cout<<Ans<<endl;
}
}
cout<<Ans;
return 0;
}
京公网安备 11010502036488号