纯用栈做居然90pts 求教
查看原帖
纯用栈做居然90pts 求教
515246
XPXPXP233楼主2024/3/14 13:06

一开始知道应该动态规划 但是不知道转移方程该怎么写 想了一会儿之后想到一个法子 但没证明正确性

具体内容就是:

第一次遍历字符串 得到每个字符的出现次序 将其当作他们各自对应的权值 所以对于一个字符串PGBHGBP就可以看成1234231

第二次遍历字符串 用一个栈来记录权值严格递增序列 每当向后增加了一个递增序列 意味着必须多一次涂色, 例如:

原来的栈是123 又进来一个4 栈此时向后增加一个变成了1234 意味着必须多一次涂色才能涂出来4 因此ans++ 原来的栈是123 此时进来了一个2 栈就退两次栈 然后把2填入 这个操作的含义大概是 新加入的2这个和原来的2可以相当于画到一起 即1222然后画上一笔3变成1232 但是3就显然被隔离开来了 将栈中的3退栈就对应着它被隔离开来了

所以总体来说直接维护一个严格单调递增栈 然后统计这个栈被延长了多少次就相当于最少画多少笔

说的很乱 因为我自己都不知道这个做法到底是不是严格正确的 但最终的结果是拿了90pts... 所以首先想知道这个做法为啥能对这么多个点 然后想知道错掉的#3是少考虑了什么情况

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<stdio.h>
#include<cmath>
#include<algorithm>
#include<vector>
#include <string>
#include <stack>
using namespace std;

string s;
int w[256];

int main() {
	cin >> s;
	int wtop = 1;
	for (int i = 0; i < s.size(); i++) {
		if (w[s[i]])
			continue;
		w[s[i]] = wtop++;
	}
	stack<char> st;
	st.push(0);			// 栈底垫上一个0  之后栈就不会空了
	int ans = 0;
	for (int i = 0; i < s.size(); i++) {
		if (w[st.top()] >= w[s[i]]) {	// 严格递增序列未被延长 说明前面有相同颜色可以一路画过来
			while (w[st.top()] >= w[s[i]]) 
				st.pop();
		}
		else {	// 严格递增序列被延长 必须多画一笔
			ans++;
		}
		st.push(s[i]);
	}
	cout << ans;
	return 0;
}
2024/3/14 13:06
加载中...