开始想用分治,找到中间的一个小于的客栈,然后用到它的两边的客栈的贡献就可以用前缀和轻易算出。然后递归处理左右。

后来发现没有这个必要,从左向右扫一遍就好了。

每次找到当前第一个小于的客栈,这样它前面的客栈与他自己的贡献便可以处理。

预处理,主过程.

#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;
}