今天会了两题,但是只过了一题,还有一题没调出来。
下午听了USACO讲评,会了T2, T3, 开始实现。
T3大体思路是先预处理一个类似于后缀最小值的东西。
然后直接扫一遍。
code:
#include<bits/stdc++.h>
//#define int long long
#define debug puts("原始人,启洞!");
using namespace std;
const int N = 3e5 + 10;
int a[N][10], f[N][10];//0 even 1 odd
int oddmx[N], oddmn[N], evenmx[N], evenmn[N];
int ans[N], b[N][10];
int n, m, k;
bool check(bool flag, int n){
int res = n;
for(int i = 1; i <= m; i++){
if (res + f[i][0] > 0) {
if (!flag) cout << "Even ";
res += b[i][0];
} else if (res + f[i][1] > 0) {
if (!flag) cout << "Odd ";
res += b[i][1];
} else return 0;
}
return 1;
}
int main() {
// freopen(".in", "r", stdin);
// freopen(".out", "w", stdout);
int T;
cin >> T;
while(T--){
cin >> n >> m >> k;
for(int i = 1; i <= m; i++){
bool flag_even = 0, flag_odd = 0;
int maxn_even = -0x3f3f3f3f, maxn_odd = -0x3f3f3f3f, minn_even = 0x3f3f3f3f, minn_odd = 0x3f3f3f3f;
for(int j = 1; j <= k; j++){
cin >> a[i][j];
if(a[i][j] & 1) flag_odd = 1, maxn_odd = max(maxn_odd, a[i][j]), minn_odd = min(minn_odd, a[i][j]);
else flag_even = 1, maxn_even = max(maxn_even, a[i][j]), minn_even = min(minn_even, a[i][j]);
}
if(!flag_odd) oddmx[i] = 0, oddmn[i] = 0;
else oddmx[i] = maxn_odd, oddmn[i] = minn_odd;
if(!flag_even) evenmx[i] = 0, evenmn[i] = 0;
else evenmx[i] = maxn_even, evenmn[i] = minn_even;
}
f[m + 1][0] = f[m + 1][1] = 0;
for(int i = m; i >= 1; i--){
b[i][0] = b[i][1] = 0x3f3f3f3f;
for (int s = 0; s < 2; s++) {
// for (int j = 1; j <= k; j++) b[i][s] = min(b[i][s], (a[i][j] % 2 == s ? 1 : -1) * a[i][j]);
if(!s){
if(!oddmx[i]) b[i][s] = evenmn[i];
else b[i][s] = -1 * oddmx[i];
}else{
if(!evenmx[i]) b[i][s] = oddmn[i];
else b[i][s] = -1 * evenmx[i];
}
f[i][s] = b[i][s];
f[i][s] += max(f[i + 1][0], f[i + 1][1]);
if (f[i][s] > 0) f[i][s] = 0;
}
}
if(check(1, n)){
if(check(0, n)) cout << endl;
// else ;
}else{
cout << -1 << endl;
}
}
return 0;
}//by hwl
T2是道构造分类讨论:
注:段数,指的是不同颜色交替次数(例:12212 段数为4)。
先确定C容器装什么颜色,当A,B栈底层颜色相同时,C取另一种颜色。
之后,当A,B顶部颜色相同时,将段数多的合到段数少的。
如果不一样则其中一个和C容器颜色相同会合到C中。
Code(WA):
#include<bits/stdc++.h>
//#define int long long
#define debug puts("原始人,启洞!");
using namespace std;
const int N = 1e5 + 10;
char ch1[N], ch2[N];
stack<int> s1, s2, s3;
int z, tot1, tot2, m, res1, res2;
pair<int, int> ans[N];
int main(){
// freopen(".in", "r", stdin);
// freopen(".out", "w", stdout);
int T;
cin >> T;
for(int _ = 1; _ <= T; _++){
int n, p;
tot1 = tot2 = 0;
cin >> n >> p;
scanf("%s", ch1 + 1);
scanf("%s", ch2 + 1);
int ca, cb;
for(int i = 1; i <= n; i++){
s1.push(ch1[i] - '0');
s2.push(ch2[i] - '0');
if(ch1[i] != ch1[i - 1]) res1++;
if(ch2[i] != ch2[i - 1]) res2++;
if(i == 1) ca = ch1[i] - '0';
if(i == 1) cb = ch2[i] - '0';
}
if(ca == cb) z = 3 - ca;
else z = ca;
// cout << "op : " << z << endl;
while(!s1.empty() && !s2.empty()){
if(res1 == 1 || res2 == 1) break;
if(s1.top() == s2.top()){
int col = s1.top();
while(!s1.empty()){
if(s1.top() == col) tot1++;
else break;
s1.pop();
}
while(!s2.empty()){
if(s2.top() == col) tot2++;
else break;
s2.pop();
}
if(res1 > res2){
res1--;
ans[++m] = {1, 2};
// cout << 1 << " " << 2 << endl;
tot2 += tot1;
while(tot2--) s2.push(col);
}else {
res2--;
ans[++m] = {2, 1};
// cout << 2 << " " << 1 << endl;
tot1 += tot2;
while(tot1--) s1.push(col);
}
tot1 = tot2 = 0;
}else{
if(s1.top() == z){
ans[++m] = {1, 3};
// cout << 1 << " " << 3 << endl;
int col = s1.top();
while(!s1.empty()){
if(s1.top() == col) tot1++;
else break;
s1.pop();
}
while(tot1--) s3.push(col);
}
if(s2.top() == z){
ans[++m] = {2, 3};
// cout << 2 << " " << 3 << endl;
int col = s2.top();
while(!s2.empty()){
if(s2.top() == col) tot2++;
else break;
s2.pop();
}
while(tot2--) s3.push(col);
}
tot1 = tot2 = 0;
}
}
if(!s1.empty()) ans[++m] = {3, 2};
else ans[++m] = {3, 1};
cout << m << endl;
// continue;
if(p != 1) for(int i = 1; i <= m; i++) cout << ans[i].first << " " << ans[i].second << endl;
while(!s1.empty())s1.pop();
while(!s2.empty())s2.pop();
m = res1 = res2 = 0;
}
return 0;
}//by hwl