CF1097C Yuhao and a Parenthesis

CF1097C Yuhao and a Parenthesis

stl 乱搞做法,感觉比正解更直接。

  • 每个字符串内部能匹配的尽可能匹配。
  • 匹配完成后,检验剩余序列是否只含有 ( 或只含有 ) 或为空,如果符合条件,插入待选序列。
  • 在待选序列中尽可能匹配。

code

  • 用一个 set<pair<string, int> > 维护新字符串和位置两个信息。
  • 记录一个 vis 表示当前位置有没有用过。
  • 依次遍历每个新字符串 \(s\),查询 \(s\) 的翻转是否在 set 中存在。

(((()))) 的翻转,不是 )))( 的翻转。

具体实现可以利用 pair 的双关键字排序查询 lower_bound(rev(s), -1)

#include<bits/stdc++.h>
using namespace std;

char stk[500000];
int tt;

bool check(string s) {
	int t = 0;
	for(char c : s) if(c == '(') ++ t;
	return (t == (int)s.size()) || t == 0;
}

string get_rev(string s) {
	string t = s;
	reverse(t.begin(), t.end());
	for(char &c : t) c == '(' ? (c = ')') : (c = '(');
	return t;
}

int main() {
	ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
	int n;
	cin >> n;
	vector<string> ss(n);
	set<pair<string, int> > se;
	vector<bool> vis(n, 0);
	for(int i = 0; i < n; ++ i) {
		cin >> ss[i];
		tt = -1;
		for(auto c : ss[i]) {
			if(~ tt && stk[tt] == '(' && c == ')') -- tt;
			else stk[++ tt] = c;
		}
		ss[i].clear();
		for(int j = 0; j <= tt; ++ j) ss[i] += stk[j];
		if(check(ss[i])) se.emplace(ss[i], i);
		else vis[i] = 1;
	}
	int ans = 0;
	for(int i = 0; i < n; ++ i) {
		if(vis[i]) continue;
		se.erase(se.find({ss[i], i}));
		vis[i] = 1;
		string t = get_rev(ss[i]);
		auto it = se.lower_bound({t, -1});
		if(it != se.end()) {
			auto [rev, j] = *it;
			if(rev == t) {
				vis[j] = 1;
				++ ans;
				se.erase({ss[j], j});
			}
		}
	}
	cout << ans << '\n';
	return 0;
}
posted @ 2024-01-08 19:48  Lu_xZ  阅读(8)  评论(0编辑  收藏  举报