序列I 题解
题目id:11050
题目描述
给定一个序列\(a=a_1,a_2,...,a_n\),有以下两种操作:
- 若\(a_i=a_{i+1}\),则可将\(a_i\)与\(a_{i+1}\)同时加\(1\)
- 将\(a_i+2\)
解题思路
第一眼莫名想到了二分(狗头)
括号匹配大家都做过吧,这题思路其实也差不多,都用栈解决。
- 操作\(1\)可以改变相邻且相同的两个数字的奇偶性(奇数\(+1=\)偶数,偶数\(+1=\)奇数)
- 操作二不会改变数字的奇偶性
那么我们可以先执行操作一,直到所有数都是奇数\(/\)都是偶数为止,再通过操作\(2\)就一定可以转换成相同的。
那么这和括号匹配有什么关系呢?
我们先求出每一个数是否是奇数(用\(1/0\)表示),如果当时栈顶元素与求得的值相同且栈不为空,则将栈顶元素出栈(这两个数可以转化为相同类型的数(奇数\(/\)偶数))
最后,如果栈里元素个数>\(1\)说明剩下的元素无法转化为相同类型的数(奇数\(/\)偶数),输出\(NO\)
如果\(\leq 1\),则输出\(YES\)。
是不是和括号匹配很像?
括号匹配是每次取出括号,这题是每次取出\(1/0\)比较而已。
AC Code
#include<bits/stdc++.h>
#define N 1000007
#define INF 1e18
#define MOD 998244353
#define LL long long
#define pb push_back
#define lb long double
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define IOS ios::sync_with_stdio(0),cin.tie(nullptr),cout.tie(nullptr)
using namespace std;
LL T,n,a[N];
int main()
{
IOS;
cin>>T;
while(T--)
{
stack<int>s;
cin>>n;
for(LL i=1,a;i<=n;++i)
{
cin>>a;
if(!s.empty()&&s.top()==(a&1))
s.pop();
else
s.push(a&1);
}
if((LL)(s.size())>1)
cout<<"NO\n";
else
cout<<"YES\n";
}
return 0;
}