Loading

CF1861C Queries for the Array

CF1861C Queries for the Array

不太一样的写法,感觉比较容易理解一点。码量也比较短。

首先我们要发现:一个序列如果目前是升序的,那么它不管删多少个数(中间不再加数),最终还是升序的;如果目前不是升序,那么不管加多少个数,最终也不是升序。

这启发我们用两个数组 \(up_i\)\(down_i\) 记录当前长度为 \(i\) 的序列是升序还是不是升序。如果存在一个时刻序列长度为 \(i\),并且 \(up_i\)\(down_i\) 都是 \(1\),也就是既是升序也不是升序,那么就不合法。(情况1)

不合法的情况还有一种,就是当序列长度小于等于 \(1\) 时,操作序列说此时不是升序,那么根据题意,也是不合法的。(情况2)

\(up\)\(down\) 的转移非常简单,如果长度 \(now\)\(1\),并且 \(up_{now}=1\),那么 \(up_{now-1}=up_{now}\),同时把 \(up_{now}=down_{now}=0\),表示未知;如果长度 \(now\)\(1\),那么只需要转移 \(down_{now+1}=down_{now}\)

所以这题我们只需要发现上面的性质就好写了,虽然比别人多个数组来做有点蠢。

AC code:

#include <bits/stdc++.h>
typedef long long ll;
int read() {
	int x = 0, f = 1;
	char c = getchar();
	while(!isdigit(c)) {
		if(c == '-') f = -1;
		c = getchar();
	}
	while(isdigit(c)) {
		x = (x << 3) + (x << 1) + (c - '0');
		c = getchar();
	}
	return x * f;
}
int t;
char a[200010];
int up[200010], down[200010];
void Solve() {
	t = read();
	while(t--) {
		std::cin >> a + 1;
		int n = strlen(a + 1), now = 0;
		bool flg = 0;
		memset(up, 0, sizeof(up));
		memset(down, 0, sizeof(down)); //这样初始化没有 tle 有点神奇。
		for(int i = 1; i <= n; i++) {
			if(a[i] == '+' || a[i] == '-') {
				if(a[i] == '+') {
					down[now + 1] = down[now];
					now++;
				}
				else {
					down[now] = 0;
					if(up[now]) up[now - 1] = up[now]; //注意判断,因为这个调了好久qwq
					up[now] = 0;
					now--;
				}
			}
			else {
				if(now <= 1 && a[i] == '0') flg = 1; //情况2
				if(a[i] == '1') up[now] = 1;
				else down[now] = 1; //根据操作序列更新数组
				if(up[now] && down[now]) flg = 1; //情况1
			}
		}
		if(flg) std::cout << "NO\n";
		else std::cout << "YES\n";
	}
}

int main() {
	
	Solve();

	return 0;
}
posted @ 2024-03-24 11:08  Fire_Raku  阅读(39)  评论(0)    收藏  举报