[luoguP1053] 篝火晚会(贪心 + 乱搞)

传送门

 

假设第一个位置是1,那么枚举它的左右两边是谁,有两种情况,然后可以递推求出序列。

然后可以贪心,两个序列有多少个不同的数,答案就是多少,具体为啥,yy一下即可

然后就是判断递推求出的序列和目标序列最少有多少个不同,也就是最大有多少个相同

因为是环,得破环为链,然后再判断的话是 n^2 的,显然超时。

另一个思路,就是不用破环为链,随便找一个节点为起点

看看每个位置的数到目标位置向左移的距离x,f[x]++

如果两个数到目标位置的距离相同,那么选其中一个数到目标位置后,另一个数也能到目标位置,多个数同理

这样我们就找最大的f[x]即可,n-f[x]为答案

 

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 60001

using namespace std;

int n, ans;
int f[N], a[N], X[N], Y[N];

inline int read()
{
	int x = 0, f = 1;
	char ch = getchar();
	for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
	for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
	return x * f;
}

inline void work()
{
	int i;
	memset(a, 0, sizeof(a));
	memset(f, 0, sizeof(f));
	a[1] = 1, a[2] = Y[1];
	for(i = 2; i < n; i++)
		if(a[i - 1] != X[a[i]] && a[i - 1] != Y[a[i]])
		{
			puts("-1");
			exit(0);
		}
		else a[i + 1] = a[i - 1] ^ X[a[i]] ^ Y[a[i]];
	if(a[n] != X[1] || a[n - 1] ^ X[a[n]] ^ Y[a[n]] ^ a[1])
	{
		puts("-1");
		exit(0);
	}
	for(i = 1; i <= n; i++)
		f[((i - a[i]) % n + n) % n]++;
	for(i = 0; i < n; i++)
		ans = max(ans, f[i]);
}

int main()
{
	int i;
	n = read();
	for(i = 1; i <= n; i++)
	{
		X[i] = read();
		Y[i] = read();
	}
	work();
	swap(X[1], Y[1]);
	work();
	printf("%d\n", n - ans);
	return 0;
}

  

posted @ 2017-10-16 16:20  zht467  阅读(163)  评论(0)    收藏  举报