2024.3.6 学习日志

今天会了两题,但是只过了一题,还有一题没调出来。

下午听了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

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值