完美字符子串 单调队列预处理+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线段树优化的更多相关文章
- [USACO2005][POJ3171]Cleaning Shifts(DP+线段树优化)
题目:http://poj.org/problem?id=3171 题意:给你n个区间[a,b],每个区间都有一个费用c,要你用最小的费用覆盖区间[M,E] 分析:经典的区间覆盖问题,百度可以搜到这个 ...
- HDU4719-Oh My Holy FFF(DP线段树优化)
Oh My Holy FFF Time Limit: 5000/2500 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others) T ...
- UVA-1322 Minimizing Maximizer (DP+线段树优化)
题目大意:给一个长度为n的区间,m条线段序列,找出这个序列的一个最短子序列,使得区间完全被覆盖. 题目分析:这道题不难想,定义状态dp(i)表示用前 i 条线段覆盖区间1~第 i 线段的右端点需要的最 ...
- zoj 3349 dp + 线段树优化
题目:给出一个序列,找出一个最长的子序列,相邻的两个数的差在d以内. /* 线段树优化dp dp[i]表示前i个数的最长为多少,则dp[i]=max(dp[j]+1) abs(a[i]-a[j])&l ...
- 【uva1502/hdu4117-GRE Words】DP+线段树优化+AC自动机
这题我的代码在hdu上AC,在uva上WA. 题意:按顺序输入n个串以及它的权值di,要求在其中选取一些串,前一个必须是后一个的子串.问d值的和最大是多少. (1≤n≤2×10^4 ,串的总长度< ...
- Contest20140906 ProblemA dp+线段树优化
Problem A 内存限制 256MB 时间限制 5S 程序文件名 A.pas/A.c/A.cpp 输入文件 A.in 输出文件 A.out 你有一片荒地,为了方便讨论,我们将这片荒地看成一条直线, ...
- POJ 3171.Cleaning Shifts-区间覆盖最小花费-dp+线段树优化(单点更新、区间查询最值)
Cleaning Shifts Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 4721 Accepted: 1593 D ...
- JZOJ 4738. 神在夏至祭降下了神谕 DP + 线段树优化
4738. 神在夏至祭降下了神谕 Time Limits: 1000 ms Memory Limits: 262144 KB Detailed Limits Goto ProblemSet D ...
- hdu3698 Let the light guide us dp+线段树优化
http://acm.hdu.edu.cn/showproblem.php?pid=3698 Let the light guide us Time Limit: 5000/2000 MS (Java ...
随机推荐
- [转帖]B树索引和位图索引的结构介绍
B树索引和位图索引的结构介绍 http://blog.itpub.net/12679300/viewspace-1174236/ 一 前言:? ROWID:包含键值的行的行ID,(查找块的最快方法, ...
- 使用无图形界面启动Centos
Centos有些时候我们是不需要图形界面的 centos默认安装成功后是有图形界面的,为了减少系统开销,有时候我们需要无图形界面启动linux(centos7) systemctl set-defau ...
- lmir 随笔
近期需要研究一些特征工程的工作,就打算把微软之前公布出来的特征都复现一遍,今天遇到的特征是 LMIR, 其实也就是language model for information retrieval的简写 ...
- 论文笔记:GREEDY FUNCTION APPROXIMATION: A GRADIENT BOOSTING MACHINE
Boost是集成学习方法中的代表思想之一,核心的思想是不断的迭代.boost通常采用改变训练数据的概率分布,针对不同的训练数据分布调用弱学习算法学习一组弱分类器.在多次迭代的过程中,当前次迭代所用的训 ...
- SpringBoot中resources配置文件application.properties
#项目名server.servlet.context-path=/springboot-day1#端口号server.port=8989 #datasource数据库连接信息#urlspring.da ...
- 【转载】Javascript使用Math.floor方法向下取整
在Javascript的数值运算中,很多时候需要对最后计算结果向下取整,Math.floor是javascript中对计算结果向下取整的函数,它总是将数值向下舍入为最接近的整数.此外Math.ceil ...
- django使用admin站点上传图片
Django有提供文件系统支持,在Admin站点中可以轻松上传图片.使用Admin站点保存图片,需要安装Python的图片操作包 pip install Pillow 1 配置 默认情况下,Dja ...
- JavaScript: 自动类型转换
我们都知道,JavaScript是类型松散型语言,在声明一个变量时,我们是无法明确声明其类型的,变量的类型是根据其实际值来决定的,而且在运行期间,我们可以随时改变这个变量的值和类型,另外,变量在运行期 ...
- C++(三十八) — 继承方式、访问控制、构造和析构、虚继承
派生类继承了基类的所有成员,但不包含 构造函数.析构函数.默认赋值运算符. 1.继承方式.访问控制 (1)protected属性:类的对象不能访问该属性成员,但派生类的成员函数可以访问基类的prot ...
- 自定义Lombok注解
Java 是一门"繁琐"的语言,使用 Lombok 可以显著地减少样板代码.比如使用 @Getter 注解可以为你的私有属性创建 get 方法. 源代码 @Getter priva ...