BZOJ 1702: [Usaco2007 Mar]Gold Balanced Lineup

有好多叫Balanced Lineup的题目……

题目大意很清楚就不再重复


因为要求[i,j]区间第k个数字的数量


我们用sum[i][k]表示前i个数字中,第k个数字的数量总和

显然 如果[i,j]满足条件的话, sum[j][k] - sum[i - 1][k]  (   1<=  k <= max_k) 是全部相等的


我们用样例来解释:

7 3
7
6
7
2
1
4
2

这写数字对应的二进制分别为:

7 111
6 110
7 111
2 010
1 001
4 100
2 010
每一行的sum分别为:

0: 0 0 0

1: 1 1 1

2: 2 2 1

3: 3 3 2

4: 3 4 2

5: 3 4 3

6: 4 4 3

7: 4 5 3


sum[j][k]用b1 b2 b3表示 sum[i - 1][k]用a1 a2 a3表示

(b1 - a1) == (b2 - a2) == (b3 - a3) == P(b1 - a1)

所有式子减去(b1 - a1)得到:

((b2 -b1) -(a2 - a1)) == ((b3 - b1) - (a3 - a1)) == P - (b1 - a1) == 0


也就是说[i,j]满足条件的话,满足下面的条件就可以了~

b2 -b1 == a2 -a1

b3 - b1 == a3 - a1


也就是说sum[i][k] -= sum[i][1] ( 1 < k <= max_k) sum[i][0] = 0;


然后只要判断sum[j][k] 和sum[i - 1][k] (1 < k <= max_k)是否相等就行了,同时找一个最大j就行了~


我的程序是倒着穷举i-1,找到对应的和自己相同的最大的j

用的是平衡树,插入的时候顺便记录他的序号, 因为是倒着插,所以如果能找到相同的节点的话就不需要再重复插入了。


在程序中,我为了偷懒使用了map,同时为了解决sum是数字的问题,我把他们变为字符串丢到map里去了~ 程序效率不是很高,但是比较容易写。


ACcode

#include 
#include 
#include 
#include 
using namespace std;

const int max_n = 100000 + 10;
const int max_m = 30 + 2;

int n, m, read_num, ans = 0;
int sum[max_n][max_m], t;
#define rm read_num

map q;
map::iterator it;


inline int get(int k,int p) //
{
	return (k >> (p - 1))&1;
}

char str[200];
inline string change(int *a)
{
	t = 0;
	for (int i = m; i > 1; -- i)
	{
		int tmp = a[i];
		if (!tmp)	str[t ++] = '0';
		while (tmp)
		{
			str[t ++] = tmp % 10 +'0';
			tmp /= 10;
		}
	}
	str[t] = '\0';
	return str;
}

inline void read(int &x)
{
       char ch;
       while (ch=getchar(),ch>'9' || ch<'0') ;
       x=ch-48;
       while (ch=getchar(),ch<='9' && ch>='0') x=x*10+ch-48; 
}

int main()
{
	read(n);	read(m);
	for (int i = 1; i <= n; ++ i)
	{
		read(rm);
		for (int j = 1; j <= m; ++ j)	sum[i][j] = get(rm, j);
		for (int j = 1; j <= m; ++ j)	sum[i][j] += sum[i - 1][j];
	}
	for (int i = 1; i <= n; ++ i)	
	{
		for (int j = 2; j <= m; ++ j)
			sum[i][j] -= sum[i][1];
		sum[i][1] = 0;
	}
	for (int i = n; i >= 0; -- i)
	{
		if ((it = q.find(change(sum[i]))) != q.end())	ans = max(ans, (*it).second - i);
		else q[change(sum[i])] = i;
	}
	printf("%d\n", ans);
	return 0;
}








你可能感兴趣的:(BZOJ,USACO月赛)