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个整数 ...
随机推荐
- 稀疏表达是要求信号在该模型下的sparse code,只有少数的non-zero elements
为什么sparse representation比起其它成分分析方法(DFT,Wavelet)能得到更好的效果? - 知乎 https://www.zhihu.com/question/241241 ...
- 解决juqery easyui combobox只能选择问题
1.首先设定框为 combobox样式,该字段值为了进行值的显示 <tr class="odd_row"> <td class="TableLabel_ ...
- ubuntu 16.04 Eclipse 图标显示为 ?(已解决)
这个问题挺好解决: sudo gedit /usr/share/applications/eclipse.desktop在这个文件中将Icon=/home/soyo/eclipse/icon.xpm, ...
- Maximum Gap 典型线性排序
https://leetcode.com/problems/maximum-gap/ Given an unsorted array, find the maximum difference betw ...
- 深入浅出Android makefile(1)--初探(转载)
转载:http://nfer-zhuang.iteye.com/blog/1752368 一.说明 android build system是一个非常庞大的系统,要编译Android工程.修改或新增A ...
- bzoj 2199: [Usaco2011 Jan]奶牛议会【2-SAT】
好久没写2-SAT了啊,还以为是网络流 设点x为选,x'为不选,因为一头牛至少要满足一个条件,所以对于牛条件的两个点,选了一个不符合的点,就要选另一个符合的点,这样连两条边 然后枚举所有议案的选和不选 ...
- 17年day3
/* 嗯,又一天. 时日无多了,还能蹦哒几天? 上午依旧考试,日常挂T1,读错题.还是好困. 兔子说明天晚上要请我们吃水饺~~~~去年就没这待遇. 下午打开邮箱一看,咦?嗯. 昨晚做噩梦NOIP考了状 ...
- hdu1512 Monkey King(并查集,左偏堆)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1512 题目大意:有n个猴子,一开始每个猴子只认识自己.每个猴子有一个力量值,力量值越大表示这个猴子打架 ...
- rman 问题
1. RMAN Repeatedly Fail To Backup Archivelogs with RMAN-20242 Cause: There is a mis-match between th ...
- 专题七:UDP编程补充——UDP广播程序的实现
一.程序实现 UDP广播程序的实现代码: using System; using System.Net; using System.Net.Sockets; using System.Text; us ...