Luogu P3797 妖梦斩木棒
解题思路
用线段树做这个就不用说了吧,但是要维护的东西确实很神奇。在每一个节点上都维护一个$lbkt$,表示这个区间上最靠左的右括号的位置;一个$rbkt$,表示这个区间上最靠右的左括号的位置。还有一个$sum$,表示这段区间(除去左右端点)上有几段完整的木棒。
注意如果一个区间内没有左右括号的话,那$lbkt=0,rbkt=0$
然后再考虑如何建树。首先想到的是第一个节点,它代表的区间是$1-n$,他的$lbkt$是$n$,$rbkt$是$1$。然后对于包含左右端点的区间进行一下特判,类似于第一个节点的操作,其余的就没啥好说的了,要是再不会就退群吧
这道题目唯一良心的地方就是那个单点修改,还好没给整成区间修改。那我们怎么单点修改呢?因为是单点修改,修改的时候$l=r$,所以可以很容易的确定$lbkt$和$rbkt$。如果是'X'的话,那么这两个值都是$0$。$sum$的维护也不难,修改了之后无非只有两种情况,那就是想修改了之后左右儿子多出了一段木棒。也有可能没有多处,所以只需要把左右儿子的$sum$加起来,再判断修改了之后能不能构成一段新的木棒。
询问也没啥好说的
附上代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define Lson (k << 1)
#define Rson (k << 1) + 1 using namespace std;
const int maxnode = 8e5+;
int n, m;
struct node {
int l, r, sum, lbkt, rbkt;
}tree[maxnode];
inline void build(int k, int ll, int rr) {
tree[k].l = ll, tree[k].r = rr;
if(k == ) { tree[k].sum = , tree[k].lbkt = n, tree[k].rbkt = ; }
else {
tree[k].sum = ;
if(tree[k].l == ) tree[k].rbkt = ;
if(tree[k].r == n) tree[k].lbkt = n;
}
if(tree[k].l == tree[k].r) return ;
int mid = (tree[k].l + tree[k].r) >> ;
build(Lson, tree[k].l, mid), build(Rson, mid+, tree[k].r);
}
inline void update(int k, int x, int y) {
if(tree[k].l == tree[k].r && tree[k].l == x) {
if(y == ) tree[k].rbkt = x, tree[k].lbkt = ;
if(y == ) tree[k].rbkt = , tree[k].lbkt = ;
if(y == ) tree[k].rbkt = , tree[k].lbkt = x;
return ;
}
int mid = (tree[k].l + tree[k].r) >> ;
if(mid >= x) update(Lson, x, y);
if(mid < x) update(Rson, x, y);
tree[k].sum = tree[Lson].sum + tree[Rson].sum;
tree[k].sum += min(tree[Lson].rbkt, ) * min(tree[Rson].lbkt, );
if(tree[Lson].lbkt > ) tree[k].lbkt = tree[Lson].lbkt;
else if(tree[Lson].rbkt == and tree[Lson].sum == )
tree[k].lbkt = tree[Rson].lbkt;
else tree[k].lbkt = ;
if(tree[Rson].rbkt > ) tree[k].rbkt = tree[Rson].rbkt;
else if(tree[Rson].lbkt == and tree[Rson].sum == )
tree[k].rbkt = tree[Lson].rbkt;
else tree[k].rbkt = ;
}
inline int queryl(int k, int l, int r) {
if(tree[k].lbkt <= r && tree[k].lbkt >= l) return tree[k].lbkt;
else return ;
}
inline int queryr(int k, int l, int r) {
if(tree[k].rbkt <= r && tree[k].rbkt >= l) return tree[k].rbkt;
else return ;
}
inline int Query(int k, int l, int r) {
if(tree[k].l > r || tree[k].r < l) return ;
if(tree[k].l >= l && tree[k].r <= r) return tree[k].sum;
int ans = Query(Lson, l, r) + Query(Rson, l, r);
ans += min(queryl(Rson, l, r), ) * min(queryr(Lson, l, r), );
return ans;
} int main() {
scanf("%d%d", &n, &m);
build(, , n);
int x, y, z;
char ch;
for(int i=; i<=m; i++) {
scanf("%d", &z);
if(z == ) {
cin>>x; cin>>ch;
if(ch == '(') y = ;
if(ch == 'X') y = ;
if(ch == ')') y = ;
update(, x, y);
}
else {
cin>>x>>y;
printf("%d\n", Query(, x, y));
}
}
return ;
}
Luogu P3797 妖梦斩木棒的更多相关文章
- [luogu P3797] 妖梦斩木棒 [线段树]
题目背景 妖梦是住在白玉楼的半人半灵,拥有使用剑术程度的能力. 题目描述 有一天,妖梦正在练习剑术.地面上摆放了一支非常长的木棒,妖梦把它们切成了等长的n段.现在这个木棒可以看做由三种小段构成,中间的 ...
- 洛谷 P3797 妖梦斩木棒 解题报告
P3797 妖梦斩木棒 妖梦是住在白玉楼的半人半灵,拥有使用剑术程度的能力. 题目描述 有一天,妖梦正在练习剑术.地面上摆放了一支非常长的木棒,妖梦把它们切成了等长的\(n\)段.现在这个木棒可以看做 ...
- 洛谷P3797 妖梦斩木棒
P3797 妖梦斩木棒 题目背景 妖梦是住在白玉楼的半人半灵,拥有使用剑术程度的能力. 题目描述 有一天,妖梦正在练习剑术.地面上摆放了一支非常长的木棒,妖梦把它们切成了等长的n段.现在这个木棒可以看 ...
- 洛谷 P3797 妖梦斩木棒
https://www.luogu.org/problem/show?pid=3797 题目背景 妖梦是住在白玉楼的半人半灵,拥有使用剑术程度的能力. 题目描述 有一天,妖梦正在练习剑术.地面上摆放了 ...
- AC日记——妖梦斩木棒 洛谷 P3797
妖梦斩木棒 思路: 略坑爹: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 200005 #define m ...
- luogu P3799 妖梦拼木棒
二次联通门 : luogu P3799 妖梦拼木棒 /* luogu P3799 妖梦拼木棒 用一个桶存下所有的木棒 美剧两根短的木棒长度 后随便乘一乘就 好了.. */ #include <a ...
- [Luogu3797] 妖梦斩木棒
题目背景 妖梦是住在白玉楼的半人半灵,拥有使用剑术程度的能力. 题目描述 有一天,妖梦正在练习剑术.地面上摆放了一支非常长的木棒,妖梦把它们切成了等长的n段.现在这个木棒可以看做由三种小段构成,中间的 ...
- 洛谷P3799 妖梦拼木棒
P3799 妖梦拼木棒 53通过 345提交 题目提供者orangebird 标签 难度普及/提高- 时空限制1s / 128MB 提交 讨论 题解 最新讨论更多讨论 暂时没有讨论 题目背景 上道 ...
- P3799 妖梦拼木棒 (组合数学)
题目背景 上道题中,妖梦斩了一地的木棒,现在她想要将木棒拼起来. 题目描述 有n根木棒,现在从中选4根,想要组成一个正三角形,问有几种选法? 输入输出格式 输入格式: 第一行一个整数n 第二行n个整数 ...
随机推荐
- 记一次ORA-600[13011]
SunOS 5.10 Oracle 10.2.0.2.0 开发环境某一数据库出现ora-600报错. alert.log中的报错信息: Thu Nov 13 15:11:43 2014 Errors ...
- SPOOL 命令使用实例【oracle导出纯文本格式文件】
SPOOL 命令使用实例[oracle导出纯文本格式文件] SET echo off --在用start命令执行一个sql脚本时,是否显示脚本中正在执行的SQL语句: SET ...
- 洛谷 P1131 [ ZJOI 2007 ] 时态同步 —— 树形DP
题目:https://www.luogu.org/problemnew/show/P1131 记录 x 子树内同步的时间 f[x],同步所需代价 g[x]: 直接转移即可,让该儿子子树与其它儿子同步, ...
- 最长回文子串问题 O(n)算法 manacher URAL1297 HDU3068
先来看一道简单的题,ural1297 给定一个1000长度的字符串,求最长回文子串. 看起来很Naive,乱搞一下,O(n^2)都可以解决. 再来看这个题 HDU3068 120个110000长度的字 ...
- 让你彻底明白JAVA中堆与栈的区别
原文地址:http://www.2cto.com/kf/201302/190704.html 简单的说: Java把内存划分成两种:一种是栈内存,一种是堆内存. 在函数中定义的一些基本类型的变量和对象 ...
- 使用WinSXS进行系统盘瘦身Windows 7/2008/10/2012不断变大的C盘(Windows 更新清理)
这是一款非常给力的国产良心小工具,用阿里云ECS的时候,一个C盘没多久就被坑爹的微软更新沉余文件塞满.此工具简单好用一下搞定! 操作系统: 所有 NT 6.X 内核的操作系统.比如 Windows V ...
- E20170527-ts
asset n. 资产,财产; 有价值的人或物; 有用的东西; 优点; serializer [词典] 串行(化)器(把并行数据变成串行数据的寄存器); 编程语言中,可被序列化的; inflec ...
- 洛谷 P2142 高精度减法(模板)
题目描述 高精度减法 输入输出格式 输入格式: 两个整数a,b(第二个可能比第一个大) 输出格式: 结果(是负数要输出负号) 输入输出样例 输入样例#1: 2 1 输出样例#1: 1 说明 20%数据 ...
- C语言小项目-火车票订票系统
list.h #ifndef __LIST_H__ #define __LIST_H__ #include "stdafx.h" #include <stdio.h> ...
- microPython 的逗比报错的问题
今天搞了一天,发现了各种问题,首先最终的解决办法就是重现刷固件!!!! 重刷固件就需要清除flash! cd C:\Users\sansong\AppData\Local\Programs\Pytho ...