新方法,理论对了但是过不了
查看原帖
新方法,理论对了但是过不了
81832
Starry___sky楼主2020/8/23 17:37

我的想法是使用位运算做,我把可以使用的客栈(最小花费不大于p的客栈)记为1,不能用的记为0。然后如果区间[i,j][i, j] 里有1并且colori==colorjcolor_i==color_j,那么ans就++。所以我把[1,n][1,n] 像状压一样压成一个数(记为cost)。对于[i,j][i,j]如果长度为i+j1i + 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

2020/8/23 17:37
加载中...