分析

由于我们需要求出符合要求的,但感觉比较繁琐
所以我们考虑求补集,即不符合要求的
发现,不符合要求,当且仅当:两个客栈位于两个的客栈之间
所以,我们类似一个滑动窗口向右滑动,记录各种颜色的个数
当遇到满足要求的客栈时,立马统计答案即可
最后用总方案数不符合要求的方案数即可

代码

//P1311
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>

#define LL long long
#define Lowbit(X) (X&(-X))
#define Lson (X<<1)
#define Rson (X<<1|1)
#define Cl(X,Y) memset((X),(Y),sizeof(X))
#define FOR(i,A,B) for(LL i=A;i<=B;i++)
#define BOR(i,A,B) for(LL i=A;i>=B;i--)
#define FOR_SIDE(i,A) for(LL i=Head[A];i;i=Next[i])
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
const int MAXN=2e5+10,MAXM=110;

int Col[MAXN],Cnt[MAXM],Ans,Num[MAXN];
int Total,Limit,Kind,Mine[MAXM];

inline void File() {
    freopen(".in","r",stdin);
    freopen(".out","w",stdout);
}

inline int Calc() {
    int Res=0;
    FOR(i,0,Kind-1) Res+=(Cnt[i]*(Cnt[i]-1))/2,Cnt[i]=0;
    return Res;
}

int main() {
    //File();
    scanf("%d %d %d",&Total,&Kind,&Limit);
    FOR(i,1,Total) { scanf("%d %d",&Col[i],&Num[i]); Mine[Col[i]]++; }
    FOR(i,1,Total) {
        if(Num[i]<=Limit) { Ans+=Calc(); }
        else Cnt[Col[i]]++;
    }
    Ans+=Calc();
    int Res=0;
    FOR(i,0,Kind-1) Res+=(Mine[i]*(Mine[i]-1))/2;
    printf("%d\n",Res-Ans);
    //fclose(stdin); fclose(stdout);
    system("pause");
    return 0;
}