题目描述
有一串数字 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(Tnlog 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; }