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区间合并的更多相关文章

  1. Codeforces GYM 100114 D. Selection 线段树维护DP

    D. Selection Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100114 Descriptio ...

  2. Codeforces Round #271 (Div. 2) E题 Pillars(线段树维护DP)

    题目地址:http://codeforces.com/contest/474/problem/E 第一次遇到这样的用线段树来维护DP的题目.ASC中也遇到过,当时也非常自然的想到了线段树维护DP,可是 ...

  3. [Codeforces]817F. MEX Queries 离散化+线段树维护

    [Codeforces]817F. MEX Queries You are given a set of integer numbers, initially it is empty. You sho ...

  4. 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 ...

  5. Codeforces 834D The Bakery 【线段树优化DP】*

    Codeforces 834D The Bakery LINK 题目大意是给你一个长度为n的序列分成k段,每一段的贡献是这一段中不同的数的个数,求最大贡献 是第一次做线段树维护DP值的题 感觉还可以, ...

  6. Codeforces750E. New Year and Old Subsequence (线段树维护DP)

    题意:长为2e5的数字串 每次询问一个区间 求删掉最少几个字符使得区间有2017子序列 没有2016子序列 不合法输出-1 题解:dp i,p(0-4)表示第i个数匹配到2017的p位置删掉的最少数 ...

  7. Codeforces 1383E - Strange Operation(线段树优化 DP or 单调栈+DP)

    Codeforces 题目传送门 & 洛谷题目传送门 Yet another 自己搞出来的难度 \(\ge 2800\) 的题 介绍一个奇奇怪怪的 \(n\log n\) 的做法.首先特判掉字 ...

  8. 2016shenyang-1002-HDU5893-List wants to travel-树链剖分+线段树维护不同区间段个数

    肯定先无脑树链剖分,然后线段树维护一段区间不同个数,再维护一个左右端点的费用. 线段树更新,pushDown,pushUp的时候要注意考虑链接位置的费用是否相同 还有就是树链剖分操作的时候,维护上一个 ...

  9. 【BZOJ2164】采矿 树链剖分+线段树维护DP

    [BZOJ2164]采矿 Description 浩浩荡荡的cg大军发现了一座矿产资源极其丰富的城市,他们打算在这座城市实施新的采矿战略.这个城市可以看成一棵有n个节点的有根树,我们把每个节点用1到n ...

随机推荐

  1. Android 7.1.1 又出幺蛾子了 —— 再谈 Android 上的 Wifi 连接

    在之前的博客文章中,我写了点在 Android 6 系统中连接到指定名称的 Wifi 的体验.然而,在 Android 7 中,有一些东西又变化了.另外就是在那篇文章中我说要提供代码,结果拖到这篇文章 ...

  2. python __call__ 函数

    __call__ Python中有一个有趣的语法,只要定义类型的时候,实现__call__函数,这个类型就成为可调用的. 换句话说,我们可以把这个类型的对象当作函数来使用,相当于 重载了括号运算符. ...

  3. 【SSH框架】之Struts2系列(一)

    微信公众号:compassblog 欢迎关注.转发,互相学习,共同进步! 有任何问题,请后台留言联系 1.Struts2框架概述 (1).什么是Struts2 Struts2是一种基于MVC模式的轻量 ...

  4. 转 从红帽、GitHub和Docker看开源商业模式的进阶

    从红帽.GitHub和Docker看开源商业模式的进阶 发表于2014-12-16 10:26| 7594次阅读| 来源http://stratechery.com/| 0 条评论| 作者Ben Th ...

  5. python 将base64字符串还原为图片

    今天弄验证码的时候发现,验证码的图片的src竟然是下面的这么一个一串字符串,吓到,好像不可以http请求的,第一次见,就好尴尬,去网上搜索了一下,说是: 这是Data URI scheme. data ...

  6. 【beta】视频预发布

    beta阶段视频发布地址: 秒拍: http://www.miaopai.com/show/Ivh31LgnAuWELxboH6gl7g__.htm

  7. 使用selenium遍历frame中的表单信息 ;

    遍历frame中的表单 : package webDriverPro; import java.util.List; import java.util.regex.Matcher; import ja ...

  8. Filter2D卷积运算

    图像处理中的卷积运算一般都用来平滑图像.尖锐图像求边缘等等.主要看你选择什么样的核函数了.现在核函数很多,比如高斯平滑核函数,sobel核函数,canny核函数等等.这里举一个sobel核函数的例子来 ...

  9. Java7 Fork-Join 框架:任务切分,并行处理

    概要 现代的计算机已经向多CPU方向发展,即使是普通的PC,甚至现在的智能手机.多核处理器已被广泛应用.在未来,处理器的核心数将会发展的越来越多.虽然硬件上的多核CPU已经十分成熟,但是很多应用程序并 ...

  10. list的迭代器能解决并发问题,collection 的迭代器不能解决并发问题,for可以解决并发问题

    list的迭代器能解决并发问题,collection 的迭代器不能解决并发问题 为什么list支持add,collection不支持 例如有两个人同时添加第三个元素 list的迭代器能锁定线程 只有等 ...