5.8 单调栈 & 悬线法 & 相关的题(和 dp 也多少沾点)
今日小题:一个 CF div2 的 A 的签到题,记录一下这个做法:
求一个字符串的最长非回文字符串:无解:长度为 1 或整个串每个字符都一样;有解:判断这个串是不是回文,如果不是,输出长度,如果是输出长度 - 1。感觉非常妙。不写证明,感觉非常好想...
#include<bits/stdc++.h>
using namespace std;
int T;
string s;
void finish()
{
cin >> s;
int len = s.size();
int flag = 0;
for(int i = 1; i < len; i ++ ) if(s[i] != s[i - 1]) {flag = 1;break;}
if(! flag || len == 1)
{
printf("-1\n");
return;
}
int i = 0, j = len - 1;
while(i < j)
{
if(s[i] == s[j]) {i ++;j --;}
else {flag = 0;break;}
}
if(! flag) printf("%d\n", len);
else printf("%d\n", len - 1);
}
int main()
{
scanf("%d", &T);
while(T -- ) finish();
return 0;
}
单调栈引入:SP1805 洛谷传送门
首先设想一下,如果矩形高度单增就好处理了,这样我们就可以直接从头到尾向右看,根据当前即最低点的高度和往右的高度来统计。
但矩形高度并不单增啊,那就想办法让它单增。
然后就会发现,如果当前矩形的高度已经小于前面矩形高度了话,那统计答案时它上面那一块就彻底没用了。所以我们可以记录这一段没用玩意的宽度,用一个宽度累加、高度为当前矩形高度的新矩形,也就是粉色标记的这一部分,把这一块直接替代掉。顺便更新一下答案。这样一来就能保证所有矩形的高度始终单调递增,就能按照前面的思路统计矩形了。
因此本题的实质,是用单调栈去维护一个高度单增的矩形序列。
细说思路,若当前高度比栈顶高就直接进栈,并标记初始宽度。否则,让栈顶一直出栈直到不再比当前高,每次宽度累加,用宽度乘现在处理的矩形高度(因为已满足单调),更新往前找的这一段的答案和宽度。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e5 + 10;
int n;
int a[N], s[N], w[N];
void finish()
{
ll ans = 0;
int x, top = 0;
a[n + 1] = 0;
memset(s, 0, sizeof s);
memset(w, 0, sizeof w);
for(int i = 1; i <= n; i ++ ) scanf("%d", &a[i]);
for(int i = 1; i <= n + 1; i ++ )
{
if(a[i] > s[top]) {s[++ top] = a[i]; w[top] = 1;continue;}
ll kuan = 0;
while(s[top] > a[i])
{
kuan += w[top];
ans = max(ans, kuan * s[top]);
top --;
}
s[++ top] = a[i];
w[top] = kuan + 1;
}
printf("%lld\n", ans);
}
int main()
{
while(cin>>n) finish();
return 0;
}
至于单调栈,其实就是在筛选可以选择的选项,及时排除掉已经没用了的东西,和单调队列比较类似(说白了原理一样),从而维护答案序列。
本文作者:Moyyer_suiy
本文链接:https://www.cnblogs.com/Moyyer-suiy/p/17383210.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步