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