专栏文章

【0】做题心得 - NOIP #66 - T1 【模拟】【贪心】

题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@min2y5lt
此快照首次捕获于
2025/12/01 19:42
3 个月前
此快照最后确认于
2025/12/01 19:42
3 个月前
查看原文
如何呢类 NOIP2024T1 题为什么这么多。那我没制作出来又是和一位啊。你发现序列排列问题都是一个套路:显然找到一个最优策略直接做即可。那个 T1 就是按照固定 2 个 / 1 个 / 无固定三个方面去做。然后这个题就是:
  1. 不要选相交区间,这可以合并。
  2. 不要让开头结尾被交换,因为这样区间会更长。
根据这两个策略哦显然就可以直接贪了。注意:需要两端考虑。大样例就是一坨屎。
CPP
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10,V=26+5;
int n,ans;
char a[N];
stack<int>stk[V];
int solve(){
	for(int c=0;c<26;c++)
		while(stk[c].size()) stk[c].pop();
	for(int i=1;i<=n;i++)
		stk[a[i]-'a'].push(i);
	int L=n,R=0,res=0;
	for(int i=1;i<=n&&L>i;i++){
		int ch=stk[a[i]-'a'].top(); stk[a[i]-'a'].pop();
		if(L<=ch&&ch<=R) continue;
		if(ch==n-i+1) res+=max(R-L+1,0), R=n-i;
		else L=min(L,ch), R=max(R,n-i+1); 
	}
	res+=max(R-L+1,0);
	return res;
}
int main(){
	freopen("poem.in","r",stdin);
	freopen("poem.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>a[i];
	ans=min((int)1e9,solve());
	reverse(a+1,a+n+1);
	ans=min(ans,solve());
	cout<<min(ans,n-1);
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...