codeforces Good bye 2016 E 线段树维护dp区间合并
codeforces Good bye 2016 E 线段树维护dp区间合并
题目大意:给你一个字符串,范围为‘0’~'9',定义一个ugly的串,即串中的子串不能有2016,但是一定要有2017,问,最少删除多少个字符,使得串中符合ugly串?
思路:定义dp(i, j),其中i=5,j=5,因为只需要删除2016当中其中一个即可,所以一共所需要删除的字符和需要的字符为20176,因此i和j只要5就够了。
然后转移就是dp(i,i) = 0, 如果说区间大小为1的话,那么如果是2017中的一个,那么就是dp(pos, pos+1) = 0, dp(pos,pos) = 1。但是如果pos为'6'这个字符,那么定义6这个pos=x转移就要为dp[x-1][x-1] = dp[x][x] = 1.然后我们再去转移就好了。
然后最后一定要注意线段树的合并顺序哦
//看看会不会爆int!数组会不会少了一维!
//取物问题一定要小心先手胜利的条件
#include <bits/stdc++.h>
using namespace std;
#pragma comment(linker,"/STACK:102400000,102400000")
#define LL long long
#define ALL(a) a.begin(), a.end()
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define haha printf("haha\n")
/*
定义dp(x,i,j)表示区间[0,x)内能够获得的2017的前缀长度为i的,至少要删除多少个字符
最少要删除多少个才能构成前缀为j的2017,然后我们不需要去管x,只需要用线段树去维护i,j即可。
*/
const int inf = 0x3f3f3f3f;
const int maxn = + ;
struct Node{
int dp[][];
}tree[maxn << ];
int n, q;
char ch[maxn];
map<char, int> id; inline void init(Node &t){
for (int i = ; i < ; i++)
for (int j = ; j < ; j++)
t.dp[i][j] = inf;
} Node Merge(Node a, Node b){
Node tmp; init(tmp);
for (int i = ; i <= ; i++)
for (int j = i; j <= ; j++)
for (int k = i; k <= j; k++)
tmp.dp[i][j] = min(tmp.dp[i][j], a.dp[i][k] + b.dp[k][j]);
return tmp;
} void display(Node t){
for (int i = ; i < ; i++){
for (int j = ; j < ; j++)
printf("%d ", t.dp[i][j]);
cout << endl;
}
} void buildtree(int l, int r, int o){
if (l == r){
init(tree[o]);
for (int i = ; i < ; i++)
tree[o].dp[i][i] = ;
int pos = id[ch[l]];
if (pos <= ) tree[o].dp[pos][pos] = , tree[o].dp[pos][pos + ] = ;
if (pos == ) tree[o].dp[][] = tree[o].dp[][] = ;
return ;
}
int mid = (l + r) / ;
if (l <= mid) buildtree(l, mid, o << );
if (r > mid) buildtree(mid + , r, o << | );
tree[o] = Merge(tree[o << ], tree[o << | ]);
//display(tree[o]);
} Node ans;
void query(int ql, int qr, int l, int r, int o){
if (ql <= l && qr >= r) {
if (ql == l) ans = tree[o];
else ans = Merge(ans, tree[o]);
return ;
}
int mid = (l + r) / ;
if (ql <= mid) query(ql, qr, l, mid, o << );
if (qr > mid) query(ql, qr, mid + , r, o << | );
} int main(){
int cnt = ;
id[''] = , id[''] = , id[''] = , id[''] = , id[''] = ;
for (char i = ''; i <= ''; i++) if(id.count(i) == ) id[i] = ++cnt;
cin >> n >> q;
scanf("%s", ch + );
buildtree(, n, );
for (int i = ; i <= q; i++){
int ql, qr; scanf("%d%d", &ql, &qr);
init(ans);
query(ql, qr, , n, );
if (ans.dp[][] >= inf) puts("-1");
else printf("%d\n", ans.dp[][]);
}
return ;
}
关键:线段树合并
codeforces Good bye 2016 E 线段树维护dp区间合并的更多相关文章
- Codeforces GYM 100114 D. Selection 线段树维护DP
D. Selection Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100114 Descriptio ...
- Codeforces Round #271 (Div. 2) E题 Pillars(线段树维护DP)
题目地址:http://codeforces.com/contest/474/problem/E 第一次遇到这样的用线段树来维护DP的题目.ASC中也遇到过,当时也非常自然的想到了线段树维护DP,可是 ...
- [Codeforces]817F. MEX Queries 离散化+线段树维护
[Codeforces]817F. MEX Queries You are given a set of integer numbers, initially it is empty. You sho ...
- Codeforces Round #343 (Div. 2) D. Babaei and Birthday Cake 线段树维护dp
D. Babaei and Birthday Cake 题目连接: http://www.codeforces.com/contest/629/problem/D Description As you ...
- Codeforces 834D The Bakery 【线段树优化DP】*
Codeforces 834D The Bakery LINK 题目大意是给你一个长度为n的序列分成k段,每一段的贡献是这一段中不同的数的个数,求最大贡献 是第一次做线段树维护DP值的题 感觉还可以, ...
- Codeforces750E. New Year and Old Subsequence (线段树维护DP)
题意:长为2e5的数字串 每次询问一个区间 求删掉最少几个字符使得区间有2017子序列 没有2016子序列 不合法输出-1 题解:dp i,p(0-4)表示第i个数匹配到2017的p位置删掉的最少数 ...
- Codeforces 1383E - Strange Operation(线段树优化 DP or 单调栈+DP)
Codeforces 题目传送门 & 洛谷题目传送门 Yet another 自己搞出来的难度 \(\ge 2800\) 的题 介绍一个奇奇怪怪的 \(n\log n\) 的做法.首先特判掉字 ...
- 2016shenyang-1002-HDU5893-List wants to travel-树链剖分+线段树维护不同区间段个数
肯定先无脑树链剖分,然后线段树维护一段区间不同个数,再维护一个左右端点的费用. 线段树更新,pushDown,pushUp的时候要注意考虑链接位置的费用是否相同 还有就是树链剖分操作的时候,维护上一个 ...
- 【BZOJ2164】采矿 树链剖分+线段树维护DP
[BZOJ2164]采矿 Description 浩浩荡荡的cg大军发现了一座矿产资源极其丰富的城市,他们打算在这座城市实施新的采矿战略.这个城市可以看成一棵有n个节点的有根树,我们把每个节点用1到n ...
随机推荐
- 石家庄铁道大学网站首页UI分析
今天的软件工程王老师讲了UI的设计,以前狭隘的认为只有移动设备上的界面叫UI,百度一下才发现UI其实有这么多含义:UI即User Interface的简称.泛指用户的操作界面,UI设计主要指界面的样式 ...
- 【IdentityServer4文档】- 术语&演示服务器和测试
术语 你需要了解一下,规范.文档和对象模型使用的术语有哪些. IdentityServer IdentityServer 是一个 OpenID Connect 提供程序 - 它实现了 OpenID C ...
- C++ auto_ptr智能指针的用法
C++中指针申请和释放内存通常采用的方式是new和delete.然而标准C++中还有一个强大的模版类就是auto_ptr,它可以在你不用的时候自动帮你释放内存.下面简单说一下用法. 用法一: std: ...
- linux设置时区和自动同步时间
1.设置时区 编辑 /etc/sysconfig/clock 修改 ZONE="Asia/Shanghai" 然后 cp /usr/share/zoneinfo/Asia/Sh ...
- Redis 备份数据的两种方式
既然是数据库,那就一定有数据备份方式了,而且 Redis 是内存形式的数据库,更需要数据备份了,要不然断电数据就全都丢失了. Redis 数据备份有两种方式: RDB(数据快照) AOF(记录操作日志 ...
- 【Linux笔记】Linux中inittab剖析
Linux完成内核(Kernel)引导后,会由init初始化进程调用/etc/inittab配置文件(ps -aux | less,init进程号为始终为1,是所有系统进程的起点,init进程也有一个 ...
- ios 中不new Date 的格式 不支持年月日 以‘-’ 分割的格式
new Date("2018-1-5") 在 ios 中显示 invalid date - 换做 / 则可以顺利显示 new Date("2018/1/5")
- 出现脚本错误或者未正确调用 Page()
pages/xxxx/xxxx.js 出现脚本错误或者未正确调用 Page() 自己创建的小程序出现上面报错,可能是因为 xxxx.js是一个空文件,所以才会出现未正确调用: 如果是空文件的话,解决办 ...
- ZOJ2290_Game
题目意思是这样的,给定一个数N,第一个可以减去任意一个数(不能为N本身),然后接下来轮流减去一个数字,下一个人减去的数字必须大于0,且不大于2倍上一次被减去的数字. 把N减为0的人获胜. 看完题目后不 ...
- 当使用listIterator进行迭代时候 list的迭代器可以在创建迭代器对象后 添加数据 但打印的时候不显示添加后的数据。 collection 的iterator迭代器不能添加数据 。list的对象与collection的实例对象都不能在创建迭代器后添加数据 list的迭代器保存的是循环前的数据长度