我的想法是使用位运算做,我把可以使用的客栈(最小花费不大于p的客栈)记为1,不能用的记为0。然后如果区间[i,j] 里有1并且colori==colorj,那么ans就++。所以我把[1,n] 像状压一样压成一个数(记为cost)。对于[i,j]如果长度为i+j−1并且每一位都为1的二进制数和cost进行与运算不为零就说明中间有一。
#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
const int N = 2e5 + 100;
void read(int &x)
{
x = 0;
register char s = getchar();
while(s < '0' || s > '9'){s = getchar();}
while(s >= '0' && s <= '9'){x = (x << 3) + (x << 1) + (s ^ 48); s = getchar();}
}
int f[N];
int move[N];
vector<int>col[60];
long long cost;
int n, k, p;
void init()
{
memset(move, 0, sizeof(move));
for(int i = 1; i <= n; i++)
move[i] = move[i - 1] << 1 | 1;//预处理出长度为1-n且各位为一的二进制数
}
int main()
{
read(n);read(k);read(p);
cost = 0;
for(int i = 1; i <= n; i++)
{
int a, b;
read(a);read(b);
col[a].push_back(i);
if(b <= p)
cost = cost << 1 | 1;//合法的在末尾添一
else
cost = cost << 1;//否则填0
}
init();
int ans = 0;
for(int i = 0; i < k; i++)
{
int len = col[i].size();
for(int j = 0; j < len; j++)
for(int k = j + 1; k < len; k++)
{
int a = col[i][j];
int b = col[i][k];
int len1 = b - a + 1;
if(cost & move[len1] << (n - b))//比较
ans++;
}
}
printf("%d", ans);
return 0;
}
T的问题我打算以后再优化,但是它为啥会WA