来自学长的快乐AK题——Day5 D

D——差分

Description

多个询问,
每个询问给出长度为n的2个序列a,b
每次可以对1<i<n的ai进行操作,操作后,

在这里插入图片描述

问能否通过若干次操作,使得序列a变成 b

输入

给出询问数T
第一行一个正整数n
第二行给出序列a
第三行给出序列b

输出

是否能转变,输出Yes或者No,每个询问对应一行

数据规模

20%:2<=n<=10
100%:2<=n<=1e5,0<=ai,bi<=2e9,T<=10

思路

反正我比赛的时候,对于这道题都没有想暴力的欲望,因为实在是毫无思路。

但这道题的突破口就是在这个式子上。

对这个式子进行移项,能得到两个很有意思的式子。

{ a i ′ − a i − 1 = a i + 1 − a i a i + 1 − a i ′ = a i − a i − 1 \left\{\begin{matrix} a_i^{'}-a_{i-1}=a_{i+1}-a_i \\ a_{i+1}-a_i^{'}=a_i-a_{i-1} \end{matrix}\right. {aiai1=ai+1aiai+1ai=aiai1

考虑差分的话,设s为操作前的差分数组,s为操作后的差分数组,则上式还可以写为:

{ s i ′ = s i + 1 s i + 1 ′ = s i \left\{\begin{matrix} s_i^{'}=s_{i+1} \\ s_{i+1}^{'}=s_i \end{matrix}\right. {si=si+1si+1=si

就容易发现,所谓操作只是将差分数组中的si与si+1调换位置而已,差分数组中的值不会发生改变。
也就是说,如果a,b序列的差分数组值都不同,无论怎么调换顺序都是不可能相等的。

求出序列a,b的差分数组,排序后依次判断对应的值是否相等即可。

代码

#include<iostream>
#include<cstdio>
#include<ctype.h>
#include<algorithm>
using namespace std;
const int N=1e6;
int t,n,a[N],b[N];
bool flag;
int read()
{
	int x=0,f=1;
	char c=getchar();
	while(!isalnum(c))
	{
		if(c=='-') f=-1;
		c=getchar();
	}
	while(isalnum(c))
	x=(x<<3)+(x<<1)+c-48,c=getchar();
	return x*f;
}
int main()
{
	t=read();
	for(int i=1;i<=t;i++)
	{
		n=read();
		for(int j=1;j<=n;j++)
		a[j]=read();
		for(int j=1;j<=n;j++)
		b[j]=read();
		for(int j=n;j>=1;j--)
		a[j]=a[j]-a[j-1],b[j]=b[j]-b[j-1];
		sort(a+1,a+n+1);
		sort(b+1,b+n+1);
		flag=1;
		for(int j=1;j<=n;j++)
		if(a[j]!=b[j])
		{
			flag=0;
			break;
		}
		if(flag) printf("Yes\n");
		else printf("No\n");
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值