zoukankan      html  css  js  c++  java
  • 【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(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;
    }
    
  • 相关阅读:
    php switch case的"bug"
    win7 安装redis服务
    linux 查看网卡以及开启网卡
    getSelection、range 对象属性,方法理解,解释
    关于window.getSelection
    富文本原理
    elasticsearch启动常见错误
    Linux 修改用户密码
    centos修改主机名的正确方法
    Dockerfile介绍
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/7761315.html
Copyright © 2011-2022 走看看