这场的代码真的有点烦(
等手题解然后补题,先挖坑
待补题:
C (已)
D
E (已)
A
枚举字符串,判断是否合法
#include <bits/stdc++.h>
using namespace std;
bool check(char s[], int len) {
bool flag = 0;
int cnt = 0;
for(int i = 0; i < len; ++ i) {
if(s[i] == '(') cnt++;
if(s[i] == ')') cnt--;
if(cnt < 0) return 0;
}
if(cnt > 0) return 0;
return 1;
}
bool check2(char s[], int len) {
bool flag = 0;
int cnt = 0;
for(int i = 0; i < len; ++ i) {
if(s[i] == ')') cnt++;
if(s[i] == '(') cnt--;
if(cnt < 0) return 0;
}
if(cnt > 0) return 0;
return 1;
}
int main() {
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int T;
int n;
cin >> T;
while(T--) {
string s;
cin >> s;
int len = s.size();
char t[60];
bool flag = 0;
for(int i = 0; i < len; ++ i) {
if(s[i] == 'A' || s[i] == 'B') t[i] = '(';
else {
t[i] = ')';
}
}
// cout << t << endl;
if(check(t, len) || check2(t, len)){
flag = 1;
}
for(int i = 0; i < len; ++ i) {
if(s[i] == 'A' || s[i] == 'C') t[i] = '(';
else {
t[i] = ')';
}
}
// cout << t << endl;
if(check(t, len) || check2(t, len)){
flag = 1;
}
for(int i = 0; i < len; ++ i) {
if(s[i] == 'B' || s[i] == 'C') t[i] = '(';
else {
t[i] = ')';
}
}
// cout << t << endl;
if(check(t, len) || check2(t, len)){
flag = 1;
}
if(flag) cout << "YES\n";
else cout << "NO\n";
}
}
B
枚举四个角上的涂色情况,然后判断是否合法
#include <bits/stdc++.h>
using namespace std;
int mp[10];
int n;
bool check(int x, int cntx) {
if(x < cntx) return 0;
if(x - cntx > n - 2) return 0;
return 1;
}
int main() {
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int T;
cin >> T;
while(T--) {
cin >> n;
int u, r, d, l;
cin >> u >> r >> d >> l;
bool flag = 0;
for(int i = 0; i < 16; ++ i) {
for(int k = 0; k < 4; ++ k) {
mp[k] = i >> k & 1;
}
int cntu = 0, cntr = 0, cntd = 0, cntl = 0;
cntu = mp[0] + mp[1];
cntr = mp[1] + mp[2];
cntd = mp[2] + mp[3];
cntl = mp[3] + mp[0];
// cout << cntu << " " << cntr << " " << cntd << " " << cntl << endl;
// system("pause");
if(check(u, cntu) && check(r, cntr) && check(d, cntd) && check(l, cntl)) {
flag = 1;
break;
}
}
if(flag) cout << "YES\n";
else cout << "NO\n";
}
}
C. 1D Sokoban
题意: 有一个一维数轴,你刚开始在原点,有一些点上面有箱子,另有一些点被特殊标记,你可以推箱子但不能拉箱子,也不能越过箱子,问最多能有多少个箱子在标记的位置上
T ≤ 1000 , − 1 e 9 ≤ a i & & b i ≤ 1 e 9 , ∑ n ≤ 2 e 5 ∑ m ≤ 1 e 5 T \leq 1000, -1e9 \leq a_i \&\& b_i \leq 1e9 , \sum n \leq 2e5 \sum m \leq 1e5 T≤1000,−1e9≤ai&&bi≤1e9,∑n≤2e5∑m≤1e5
思路: 原点左右可以分开做,把原点左边部分映射到右边,于是只用计算正数
昨晚的想法是:根据特殊标记做一个后缀和(多少个箱子已经正好被摆在标记位置上),枚举每个特殊标记的位置作为推箱子的最后一个点(会有连续的箱子,最后一个箱子刚好在枚举的位置),用lowerbound和upperbound判断这段连续的箱子有多少个在标记上,加上枚举点后一个点的后缀和 复杂度大概是nlogn常数可能有点大 ,wa2的第29个点,一时半会de不出来等一手官方题解
upd: 忘记判断如果在A里面upper_bound不存在的情况了((
#include <bits/stdc++.h>
using namespace std;
vector<int> al, ar, bl, br;
inline void init() {
al.clear(), ar.clear();
bl.clear(), br.clear();
}
int solve(const vector<int>& a, const vector<int>& b) {
int n = a.size(), m = b.size();
if(n == 0 || m == 1) return 0;
vector<int> suf(m + 5);
int j = n - 1;
for(int i = m - 1; i >= 0; -- i) {
suf[i] = suf[i + 1];
if(j == -1) continue;
while(a[j] > b[i] && j > 0) --j;
if(a[j] == b[i]) ++ suf[i], -- j;
}
int ans = 0;
for(int i = 1; i < m; ++ i) {
int res = suf[i + 1];
int pos = 0;
if(upper_bound(a.begin(), a.end(), b[i]) == a.end()) pos = n;
else pos = upper_bound(a.begin(), a.end(), b[i]) - a.begin();
int pp = b[i] - pos + 1;
int l = lower_bound(b.begin(), b.end(), pp) - b.begin();
res += i - l + 1;
ans = max(ans, res);
}
return ans;
}
int main() {
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int T;
cin >> T;
while(T--) {
int n, m;
cin >> n >> m;
init();
bl.push_back(0); br.push_back(0);
for(int i = 0, x; i < n; ++ i) {
cin >> x;
if(x < 0) al.push_back(-x);
else ar.push_back(x);
}
for(int i = 0, x; i < m; ++ i) {
cin >> x;
if(x < 0) bl.push_back(-x);
else br.push_back(x);
}
sort(al.begin(), al.end()); sort(bl.begin(), bl.end());
cout << solve(al, bl) + solve(ar, br) << endl;
}
}
E. A-Z Graph
题意: n个点m次操作,每次操作有三种1.可以加一条边(边上有字母),2.删去一条边,3.询问是否能有经过k个点的往返路
径,并且使得往返边上字母连成的字符串相同
n,m 2e5
思路: 简单画图可得,k为奇成立的条件是存在两个点之间有双向的边,k为偶成立的条件是存在两个点之间有双向的边并且边上的字母相同
code : // 这里pair用struct在map判断是否存在的时候会有点问题,存疑
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
#define first x
#define second y
map<pii , char> mp;
int main() {
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int n, m;
cin >> n >> m;
char op, ch;
int x, y, cnt1 = 0, cnt2 = 0;
for(int i = 0; i < m; ++ i) {
cin >> op;
if(op == '+') {
cin >> x >> y >> ch;
mp[{x, y}] = ch;
if(mp.count({y, x})) {
cnt1++;
char p = mp[{y, x}];
if(p == ch) cnt2 ++;
}
// cout << " cnttt:: " << cnt1 <<" " << cnt2 << endl;
}
else if(op == '-') {
cin >> x >> y;
char p1 = mp[{x, y}];
mp.erase({x, y});
if(mp.count({y, x})) {
cnt1--;
char p2 = mp[{y, x}];
if(p1 == p2) cnt2--;
}
}
else if (op == '?') {
cin >> x;
// cout << " cnttt:: " << cnt1 <<" " << cnt2 << endl;
if(x & 1) {
if(cnt1) cout << "YES\n";
else cout << "NO\n";
}
else {
if(cnt2) cout << "YES\n";
else cout << "NO\n";
}
}
}
}