Codeforces 750E 线段树DP
题意:给你一个字符串,有两种操作:1:把某个位置的字符改变。2:询问l到r的子串最少需要删除多少个字符,使得这个子串含有2017子序列,并且没有2016子序列?
思路:线段树上DP,我们设状态0, 1, 2, 3, 4分别为: null, 2, 20, 201, 2017的最小花费,我们用线段树来维互状态转移的花费矩阵,合并相邻的两个子串的时候直接转移即可。
代码:
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define ls (o << 1)
#define rs (o << 1 | 1)
using namespace std;
const int maxn = 200010;
int a[maxn];
char s[maxn];
struct node {
int f[5][5];
void init(int x) {
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if(i == j) continue;
f[i][j] = INF;
}
}
if(x == 2) {
f[0][0] = 1, f[0][1] = 0;
} else if (x == 0) {
f[1][1] = 1, f[1][2] = 0;
} else if (x == 1) {
f[2][2] = 1, f[2][3] = 0;
} else if (x == 7) {
f[3][3] = 1, f[3][4] = 0;
} else if (x == 6) {
f[3][3] = 1;
f[4][4] = 1;
} else if (x == -1){
for (int i = 0; i < 5; i++)
f[i][i] = INF;
} else {
for (int i = 0; i < 5; i++)
f[i][i] = 0;
}
} void print() {
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if(f[i][j] == INF) printf("inf ");
else printf("%d ", f[i][j]);
}
printf("\n");
}
}
};
node tr[maxn * 4];
node merge(node t1, node t2) {
node ans;
ans.init(-1);
// ans.init(-1);
// printf("ans\n");
// ans.print();
// printf("t1\n");
// t1.print();
// printf("t2\n");
// t2.print();
for (int i = 0; i < 5; i++) {
for (int j = i; j < 5; j++) {
for (int k = i; k <= j; k++) {
ans.f[i][j] = min(ans.f[i][j], t1.f[i][k] + t2.f[k][j]);
}
}
}
// printf("ans\n");
// ans.print();
return ans;
}
void build(int o, int l, int r) {
if(l == r) {
tr[o].init(a[l]);
return;
}
int mid = (l + r) >> 1;
build(ls, l, mid);
build(rs, mid + 1, r);
tr[o] = merge(tr[ls], tr[rs]);
}
void update(int o, int l, int r, int ql, int qr, int val) {
if(l == r) {
tr[o].init(val);
return;
}
int mid = (l + r) >> 1;
if(ql <= mid) update(ls, l, mid, ql, qr, val);
if(qr > mid) update(rs, mid + 1, r, ql, qr, val);
tr[o] = merge(tr[ls], tr[rs]);
}
node query(int o, int l, int r, int ql, int qr) {
if(l >= ql && r <= qr) {
return tr[o];
}
int mid = (l + r) >> 1;
node ans;
ans.init(-1);
if(ql <= mid && qr > mid) ans = merge(query(ls, l, mid, ql, qr), query(rs, mid + 1, r, ql, qr));
else if(ql <= mid) ans = query(ls, l, mid, ql, qr);
else if(qr > mid) ans = query(rs, mid + 1, r, ql, qr);
return ans;
}
int main() {
int n, m, l, r;
scanf("%d%d", &n, &m);
scanf("%s", s + 1);
for (int i = 1; i <= n; i++) {
a[i] = s[i] - '0';
}
build(1, 1, n);
for (int i = 1; i <= m; i++) {
scanf("%d%d", &l, &r);
node ans = query(1, 1, n, l, r);
if(ans.f[0][4] == INF) printf("-1\n");
else printf("%d\n", ans.f[0][4]);
}
}
Codeforces 750E 线段树DP的更多相关文章
- Tsinsen A1219. 采矿(陈许旻) (树链剖分,线段树 + DP)
[题目链接] http://www.tsinsen.com/A1219 [题意] 给定一棵树,a[u][i]代表u结点分配i人的收益,可以随时改变a[u],查询(u,v)代表在u子树的所有节点,在u- ...
- HDU 3016 Man Down (线段树+dp)
HDU 3016 Man Down (线段树+dp) Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Ja ...
- Bash and a Tough Math Puzzle CodeForces 914D 线段树+gcd数论
Bash and a Tough Math Puzzle CodeForces 914D 线段树+gcd数论 题意 给你一段数,然后小明去猜某一区间内的gcd,这里不一定是准确值,如果在这个区间内改变 ...
- Codeforces 750E New Year and Old Subsequence 线段树 + dp (看题解)
New Year and Old Subsequence 第一感觉是离线之后分治求dp, 但是感觉如果要把左边的dp值和右边的dp值合起来, 感觉很麻烦而且时间复杂度不怎么对.. 然后就gun取看题解 ...
- 线段树+dp+贪心 Codeforces Round #353 (Div. 2) E
http://codeforces.com/contest/675/problem/E 题目大意:有n个车站,每个车站只能买一张票,这张票能从i+1到a[i].定义p[i][j]为从i到j所需要买的最 ...
- D - The Bakery CodeForces - 834D 线段树优化dp···
D - The Bakery CodeForces - 834D 这个题目好难啊,我理解了好久,都没有怎么理解好, 这种线段树优化dp,感觉还是很难的. 直接说思路吧,说不清楚就看代码吧. 这个题目转 ...
- Codeforces 1063F - String Journey(后缀数组+线段树+dp)
Codeforces 题面传送门 & 洛谷题面传送门 神仙题,做了我整整 2.5h,写篇题解纪念下逝去的中午 后排膜拜 1 年前就独立切掉此题的 ymx,我在 2021 年的第 5270 个小 ...
- Codeforces Round #343 (Div. 2) D - Babaei and Birthday Cake 线段树+DP
题意:做蛋糕,给出N个半径,和高的圆柱,要求后面的体积比前面大的可以堆在前一个的上面,求最大的体积和. 思路:首先离散化蛋糕体积,以蛋糕数量建树建树,每个节点维护最大值,也就是假如节点i放在最上层情况 ...
- Codeforces.264E.Roadside Trees(线段树 DP LIS)
题目链接 \(Description\) \(Solution\) 还是看代码好理解吧. 为了方便,我们将x坐标左右反转,再将所有高度取反,这样依然是维护从左到右的LIS,但是每次是在右边删除元素. ...
随机推荐
- (18)C++项目练习一(功能会不断扩展)--------【聊天工具】
1.准备使用Qt和C++做一个远程(基于互联网的)聊天工具,需要实现以下功能 (1)多对多聊天功能 (2)文件传输功能 (3)注册.登录功能 (4)加好友.同意好友功能 (5)好友列表.黑名单功能(分 ...
- UOJ428. 【集训队作业2018】普通的计数题
http://uoj.ac/problem/428 题解 神仙题. 考虑最后一定是放了一个\(1\),然后把其他位置都删掉了. 再考虑到对于序列中的每个位置都对应了一次操作. 我们可以对于每个放\(1 ...
- CG-CTF | 密码重置2
跟则提示走,美滋滋: 1.找到邮箱: 2.下载备份: 3.PHP弱类型,string与int用的是“==” ........这一行是省略的代码........ if(!empty($token)&am ...
- 前端每日实战:138# 视频演示如何用纯 CSS 创作一张 iPhone 价格信息图
效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/OorLGZ 可交互视频 此视频是可 ...
- leetcode-mid-Linked list- 103. Binary Tree Zigzag Level Order Traversal
mycode 99.24% # Definition for a binary tree node. # class TreeNode(object): # def __init__(self, x) ...
- Android流媒体开发之路三:基于NDK开发Android平台RTSP播放器
基于NDK开发Android平台RTSP播放器 最近做了不少android端的开发,有推流.播放.直播.对讲等各种应用,做了RTMP.RTSP.HTTP-FLV.自定义等各种协议,还是有不少收获和心得 ...
- linux压缩文件命令-zip
首先cd到要压缩文件的目录,然后使用zip命令压缩文件 zip -r importExcel.zip importExcel -r表示递归 zip [参数] [打包后的文件名] [打包的目录路径] ...
- Openstack_通用技术_RPC 远程异步调用
目录 目录 RPC 一个通过 HTTP Request 调用操作函数的 RPC 实现样例 环境 接收 HTTP Request RPC 调用具体的操作函数 测试 RPC RPC: 同一个项目内的不同服 ...
- 自动化测试--利用opencv进行图像识别与定位
SIFT检测方法 SIFT算法就是把图像的特征检测出来,通过这些特征可以在众多的图片中找到相应的图片 import cv2 #读取图片,以1.png为例 img=cv2.imread('1.png') ...
- python正则表达式整理
正则表达式在处理字符串时很大的作用,爬虫中也经常用到,下面就将一些常用正则表达式做一整理记录,方便以后查看. ^d 表示匹配以d开头的字符串 . 表示匹配任意字符串 * 表示前面 ...