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. {ai′−ai−1=ai+1−aiai+1−ai′=ai−ai−1
考虑差分的话,设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;
}