完美字符子串 单调队列预处理+DP线段树优化
题意:有一个长度为n的字符串,每一位只会是p或j。你需要取出一个子串S(注意不是子序列),使得该子串不管是从左往右还是从右往左取,都保证每时每刻已取出的p的个数不小于j的个数。如果你的子串是最长的,那么称之为完美字符子串。求完美字符子串的长度。
乍一看比较水,然而差点没想出来。
考虑处理前缀和,p+1 j-1 那么对于一段区间[l,r]只要每一个i∈[l,r]满足presum[i]-presum[l-1]>=0即满足题意
1.单调队列预处理每个位置向前/后走的最远位置 记为f[i]/g[i]
2.枚举区间的左端点L,那么对于所有R∈[i,f[i]]找到最靠右的R满足g[R]<=i
3.R何可以通过向右移动cur优化,查找R可以用线段树优化
Code:
#include <bits/stdc++.h>
using namespace std;const int MAXN = 1000005;int n, f[MAXN], g[MAXN], sum1[MAXN], sum2[MAXN];
char s[MAXN];
int cnt, st[MAXN];void solve1()
{for(int i = 1; i <= n; i++)if(s[i] == 'p') st[++cnt] = i;else{while(cnt && sum1[st[cnt]] - sum1[i] > 1)f[st[cnt--]] = i-1;}while(cnt) f[st[cnt--]] = n;
}void solve2()
{for(int i = n; i >= 1; i--)if(s[i] == 'p') st[++cnt] = i;else{while(cnt && sum2[st[cnt]] - sum2[i] > 1)g[st[cnt--]] = i+1;}while(cnt) g[st[cnt--]] = 1;
}int mn[MAXN*4];void build(int i, int l, int r)
{if(l == r){mn[i] = (g[l] == 0) ? 0x7f7f7f7f : g[l];return;}int mid = (l + r) >> 1;build(i*2, l, mid);build(i*2+1, mid+1, r);mn[i] = min(mn[i*2], mn[i*2+1]);
}int find(int i, int l, int r, int x, int y, int k)
{if(y < l || x > r || mn[i] > k) return -1;if(l == r) return mn[i] <= k ? l : -1;int mid = (l + r) >> 1;int tmp = find(i*2+1, mid+1, r, x, y, k);if(tmp != -1) return tmp;return find(i*2, l, mid, x, y, k);
}int main ()
{scanf("%d%s", &n, s+1);for(int i = 1; i <= n; i++)sum1[i] = sum1[i-1] + (s[i] == 'p' ? 1 : -1);solve1();for(int i = n; i >= 1; i--)sum2[i] = sum2[i+1] + (s[i] == 'p' ? 1 : -1);solve2();build(1, 1, n);int cur = 1, Ans = 0;for(int i = 1; i <= n; i++) if(f[i]){int pos = find(1, 1, n, cur=max(cur, i), f[i], i);if(pos == -1) continue;Ans = max(Ans, pos - i + 1); cur = pos+1;}printf("%d\n", Ans);
}
完美字符子串 单调队列预处理+DP线段树优化相关推荐
- hdu5489 Removed Interval dp+线段树优化
现在看这题居然直接秒了...去年看的时候还以为神题.. 设以第i项为结尾的lis前缀为f[i],以第j项为结尾的lis后缀为g[i],如果求出f[i]和g[j],然后枚举i,快速找到最大的满足a[j] ...
- POJ2823 Sliding Window【单调队列】【线段树】【ST表】
Sliding Window POJ - 2823 题意: 给出一个长度为N的序列,通过一个窗口,可以看到序列中连续的K个元素,窗口从最左边出发,每次移动一个单位,对于每次移动,输出当前窗口中的最大值 ...
- Codeforces Round #620 (Div. 2) F2. Animal Observation (hard version) dp + 线段树
传送门 文章目录 题意: 思路: 题意: 比如下面这个图: 思路: 对于这个题,比较容易就能考虑到dpdpdp,设f[i][j]f[i][j]f[i][j]为到了第iii行,覆盖了[j,j+k−1][ ...
- 埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛H题小Y与多米诺骨牌(线段树优化dp)
题意 题目链接:https://www.nowcoder.com/acm/contest/91/H 来源:牛客网 题解 设l[i]l[i]l[i]为向左推第iii个骨牌最远能影响到的骨牌的编号,r[i ...
- hdu 4521(线段树优化dp)
小明系列问题--小明序列 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Pro ...
- HDU3698-Let the light guide us (线段树优化的dp)
Plain of despair was once an ancient battlefield where those brave spirits had rested in peace for t ...
- CF 474E Pillars(线段树优化DP)
CF 474E Pillars 题目描述 Marmot found a row with n n n pillars. The i i i -th pillar has the height of h ...
- AtCoder Regular Contest 085 F NRE 线段树优化dp
题意 有长度为n初始全为0的数组A和仅由0和1组成的数组B.现在给出m个区间,每次可以选择某个区间[l,r],使得A数组下标在[l,r]之间的元素变为1.问A和B最小不同位置数量是多少. n,m< ...
- 线段树优化建图详解——区间连边之技巧,吊打紫题之利器
我们从一道例题开始. CF786B Description Solution 朴素解法: 暴力连边+最短路 对于每次连边操作,我们逐一连边,最后在图上跑一遍单源最短路径算法即可. 时间复杂度 O ( ...
最新文章
- Oracle 字符集的查看和修改
- 牛客 - 街机争霸(bfs)
- 新的Azure通信服务(ACS)如何实现WebRTC?
- 介绍一个快速找出 Visual Studio Code 代码多余空格的扩展 - trailing space
- 接视频Java 数据库
- 每周一书-2016年8月28日到9月4日获奖读者公布
- linux 手动控制cpu转速,Linux 手动计算CPU使用率
- 2017年SEO推广优化怎么做
- 理解RDD的Partition
- Linux指令篇:文件系统--fdisk(转)
- 绿色版本chrome设为默认浏览器
- SOSO街景地图 API (Javascript)开发教程(1)- 街景
- 计算机编程的英语单词大全,计算机编程常用英语单词
- 【数据挖掘与商务智能决策】第十七章 神经网络
- BBN: Bilateral-Branch Network with Cumulative Learning for Long-Tailed Visual Recognition
- 上海移动HG6145D光猫之超级用户登录方法
- sql优化(面试必问一)
- 团队建设:一个团队从无到有再到高效的管理方式
- SoCFPGA-A10 内核ADRV9025设备与驱动的添加
- 计算机音乐春分秋分,春分和秋分的古诗词