解题思路

用线段树做这个就不用说了吧,但是要维护的东西确实很神奇。在每一个节点上都维护一个$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 妖梦斩木棒的更多相关文章

  1. [luogu P3797] 妖梦斩木棒 [线段树]

    题目背景 妖梦是住在白玉楼的半人半灵,拥有使用剑术程度的能力. 题目描述 有一天,妖梦正在练习剑术.地面上摆放了一支非常长的木棒,妖梦把它们切成了等长的n段.现在这个木棒可以看做由三种小段构成,中间的 ...

  2. 洛谷 P3797 妖梦斩木棒 解题报告

    P3797 妖梦斩木棒 妖梦是住在白玉楼的半人半灵,拥有使用剑术程度的能力. 题目描述 有一天,妖梦正在练习剑术.地面上摆放了一支非常长的木棒,妖梦把它们切成了等长的\(n\)段.现在这个木棒可以看做 ...

  3. 洛谷P3797 妖梦斩木棒

    P3797 妖梦斩木棒 题目背景 妖梦是住在白玉楼的半人半灵,拥有使用剑术程度的能力. 题目描述 有一天,妖梦正在练习剑术.地面上摆放了一支非常长的木棒,妖梦把它们切成了等长的n段.现在这个木棒可以看 ...

  4. 洛谷 P3797 妖梦斩木棒

    https://www.luogu.org/problem/show?pid=3797 题目背景 妖梦是住在白玉楼的半人半灵,拥有使用剑术程度的能力. 题目描述 有一天,妖梦正在练习剑术.地面上摆放了 ...

  5. AC日记——妖梦斩木棒 洛谷 P3797

    妖梦斩木棒 思路: 略坑爹: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 200005 #define m ...

  6. luogu P3799 妖梦拼木棒

    二次联通门 : luogu P3799 妖梦拼木棒 /* luogu P3799 妖梦拼木棒 用一个桶存下所有的木棒 美剧两根短的木棒长度 后随便乘一乘就 好了.. */ #include <a ...

  7. [Luogu3797] 妖梦斩木棒

    题目背景 妖梦是住在白玉楼的半人半灵,拥有使用剑术程度的能力. 题目描述 有一天,妖梦正在练习剑术.地面上摆放了一支非常长的木棒,妖梦把它们切成了等长的n段.现在这个木棒可以看做由三种小段构成,中间的 ...

  8. 洛谷P3799 妖梦拼木棒

    P3799 妖梦拼木棒 53通过 345提交 题目提供者orangebird 标签 难度普及/提高- 时空限制1s / 128MB 提交  讨论  题解 最新讨论更多讨论 暂时没有讨论 题目背景 上道 ...

  9. P3799 妖梦拼木棒 (组合数学)

    题目背景 上道题中,妖梦斩了一地的木棒,现在她想要将木棒拼起来. 题目描述 有n根木棒,现在从中选4根,想要组成一个正三角形,问有几种选法? 输入输出格式 输入格式: 第一行一个整数n 第二行n个整数 ...

随机推荐

  1. 关于Time Series Database

    今天观察了下clojure之父datomic.com的数据库 有点类似sequence数据库的变种 不过这类数据库,感觉用在移动端会更有市场: 1. 移动端需要这种可以本地存储,无删除,联网只增加,只 ...

  2. python 代码混淆工具汇总

    pyminifier Pyminifier is a Python code minifier, obfuscator, and compressor. Note For the latest, co ...

  3. Called attach on a child which is not detached

    问题:Called attach on a child which is not detached: ViewHolder#出现问题的原因 经过google后发现,出现该问题的原因是由于recycle ...

  4. JSSDK使用步骤

    绑定域名 先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”. 备注:登录后可在“开发者中心”查看对应的接口权限. 引入js文件 在需要调用JS接口的页面引入如下JS文件,( ...

  5. 2-5 原生小程序 - 语法缺点.mp4

  6. mvn 配置

    <!-- 阿里云仓库1 -->    <mirror>        <id>alimaven-1</id>        <name>al ...

  7. nginx的负载均衡的问题

    本节就聊聊采用Nginx负载均衡之后碰到的问题: Session问题 文件上传下载 通常解决服务器负载问题,都会通过多服务器分载来解决.常见的解决方案有: 网站入口通过分站链接负载(天空软件站,华军软 ...

  8. Coding Pages 服务与万网域名的配置

    1071220 http://support.huawei.com/learning/NavigationAction!createNavi?navId=MW000001_term1000190292 ...

  9. C#,VB.NET将PPT文档转换为HTML

    PPT文档主要用于展示,有时候我们需要将PPT文档转换为HTML格式方便查看.本文将介绍如何使用C#和VB.NET将PPT文档转换为HTML格式.该方案使用了.NET PowerPoint 组件Spi ...

  10. Spring框架学习-Spring和IOC概述

    一:什么是Spring框架? spring是一个分层的javase/EEfull-stack(一站式)轻量级的java开源框架.是为了解决企业开发的复杂性而创建的.框架的主要优势是分层架构,Sprin ...