【bzoj5071】[Lydsy十月月赛]小A的数字 乱搞

题目描述

有一串数字 A1,A2...An 
每次可以进行如下操作,选择一个数字 i ,将 (Ai-1 , Ai , Ai+1) 
变为 (Ai-1 + Ai , -Ai , Ai+1 + Ai) ,特别地,若 i=N ,则 (An-1 , An) 变为 (An-1 + An , -An) .
问:能否通过若干次操作得到 B1,B2...Bn ?

输入

第一行一个正整数 T 表示数据组数。
每一组数据有三行,其中:
第一行一个正整数 n,表示每一串数字的个数;
第二行 n 个用空格隔开的整数, 表示A1,A2,...An;
第三行 n 个用空格隔开的整数, 表示B1,B2,...,Bn。

输出

对于每一组数据,输出一行”YES”或”NO”(不含双引号),表示能否通过若干次操作得到 B 数列。

样例输入

2
6
1 6 9 4 2 0
7 -6 19 2 -6 6
4
1 2 3 4
4 2 1 3

样例输出

YES
NO


题解

乱搞

(前一天宋爷讲过的类似的题,bz月赛就考了。。)

对序列求前缀和,可以发现每次操作后这三(两)个位置的前缀和变化为: (Si , Si-1 , Si+1),相当于每次操作在前缀和序列中交换了它和它前面的数。

而通过交换相邻的两个数可以得到该序列的全部排列,因此直接比较A和B的前缀和序列是否为相同的序列的排列即可。排序后直接逐个比较即可。

时间复杂度$O(Tn\log n)$

#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
ll a[100010] , b[100010];
int main()
{
	int T;
	scanf("%d" , &T);
	while(T -- )
	{
		int n , i;
		scanf("%d" , &n);
		for(i = 1 ; i <= n ; i ++ ) scanf("%lld" , &a[i]) , a[i] += a[i - 1];
		for(i = 1 ; i <= n ; i ++ ) scanf("%lld" , &b[i]) , b[i] += b[i - 1];
		sort(a + 1 , a + n + 1) , sort(b + 1 , b + n + 1);
		for(i = 1 ; i <= n ; i ++ )
			if(a[i] != b[i])
				break;
		if(i > n) puts("YES");
		else puts("NO");
	}
	return 0;
}

 

posted @ 2017-10-31 14:24  GXZlegend  阅读(588)  评论(0编辑  收藏  举报