P3797 妖梦斩木棒

妖梦是住在白玉楼的半人半灵,拥有使用剑术程度的能力。

题目描述

有一天,妖梦正在练习剑术。地面上摆放了一支非常长的木棒,妖梦把它们切成了等长的\(n\)段。现在这个木棒可以看做由三种小段构成,中间的n-2段都是左右都被切断的断头,我们记做’\(X\)’,最左边的一段和最右边的一段各有一个圆头,记做’(‘和’)’。幽幽子吃饱后闲来无事,决定戏弄一下妖梦。她拿来了许多这样的三种小段木棒,来替换掉妖梦切下来的n段中的一部分,然后问妖梦一些问题。这些操作可以这样描述:

\(1\) \(x\) \(C\) 将第\(x\)个小段的木棒替换成\(C\)型,C只会是’\(X\)’,’\((\)‘,’\()\)’中的一种

\(2\) \(l\) \(r\) 询问妖梦从第\(l\)段到第\(r\)段之间(含\(l\),\(r\)),有多少个完整的木棒

完整的木棒左右两端必须分别为’(‘和’)’,并且中间要么什么都没有,要么只能有’\(X\)’。

虽然妖梦能够数清楚这些问题,但幽幽子觉得她回答得太慢了,你能教给妖梦一个更快的办法吗?

输入输出格式

输入格式:

第一行两个整数\(n\),\(m\),\(n\)表示共有\(n\)段木棒,\(m\)表示有\(m\)次操作。

木棒的初始形状为(XXXXXX......XXXXXX)。

接下来\(m\)行,每行三个整数/字符,用空格隔开。第一个整数为1或2,表示操作的类型,若类型为1,则接下来一个整数x,一个字符C。若类型为2,接下来两个整数\(l\),\(r\)。含义见题目描述。

输出格式:

对于每一个操作2,输出一行一个整数,表示对应询问的答案。

说明

对于30%的数据,1<=n,m<=1000

对于100%的数据,1<=n,m<=200000

by-orangebird


拍了一下午总算搞出来了,太毒了。

首先说一下思想,其实大概一看大家都会想到拿线段树维护,但实际上没见过类似的模型是比较难想到正解的。

我个人认为,这个维护是有一点分治的思想的(不过线段树其实也是分治的思想了emmm)

在线段树的区间里维护3个值\(dat,L,R\),分别代表区间木棍数量,最左边的右括号的坐标(没有为即为0),最右边的左括号的坐标(没有即为n+1)

对询问

左儿子的+右儿子的+合并时可能产生的一个

对修改

\(dat\)域和询问一样

\(L\)和\(R\)一样,说一个吧

比如\(L\),先拿左儿子更新,如果没更新成功(指没有左儿子括号)再尝试右儿子更新

卡点就在什么时候更新上。当然可以维护一个额外的域去判断,但不加一个额外的域时还是很坑的。。。

不直接说更新方法了,想不出来可以直接看看代码


Code:

#include <cstdio>
#define ls id<<1
#define rs id<<1|1
const int N=200010;
int n,m;
int dat[N<<2],L[N<<2],R[N<<2];
void change(int id,int l,int r,int x,int delta)
{
if(l==r)
{
L[id]=0;R[id]=n+1;
if(delta==1)//'('
R[id]=l;//最右边的左括号
else if(delta==2)//')'
L[id]=r;//最左边的右括号
return;
}
int mid=l+r>>1;
if(x<=mid)
change(ls,l,mid,x,delta);
else
change(rs,mid+1,r,x,delta);
dat[id]=dat[ls]+dat[rs]+(R[ls]<=n&&L[rs]);
L[id]=L[ls];
//如果左儿子没有左括号和右括号就可以考虑用右儿子的右括号了
if(dat[ls]==0&&R[ls]==n+1&&L[ls]==0)
L[id]=L[rs];
R[id]=R[rs];
if(dat[rs]==0&&L[rs]==0&&R[rs]==n+1)
R[id]=R[ls];
}
int query(int id,int l,int r,int ll,int rr)
{
if(l==ll&&r==rr)
return dat[id];
int mid=ll+rr>>1;
if(r<=mid)
return query(ls,l,r,ll,mid);
else if(l>mid)
return query(rs,l,r,mid+1,rr);
else
return query(ls,l,mid,ll,mid)+query(rs,mid+1,r,mid+1,rr)+(R[ls]<=n&&L[rs]&&R[ls]>=l&&L[rs]<=r);
}
void build(int id,int l,int r)
{
L[id]=0,R[id]=n+1;
if(l==1) R[id]=1;//最右边的左括号位置为1
if(r==n) L[id]=n;//最左边的右括号位置为n
if(l==r) return;
int mid=l+r>>1;
build(ls,l,mid);
build(rs,mid+1,r);
}
int main()
{
//freopen("data.in","r",stdin);
//freopen("wr.out","w",stdout);
scanf("%d%d",&n,&m);
int opt,l,r;char c;
dat[1]=1;
build(1,1,n);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&opt,&l);
if(opt==1)
{
scanf(" ");
scanf("%c",&c);
if(c=='X') change(1,1,n,l,0);
else if(c=='(') change(1,1,n,l,1);
else change(1,1,n,l,2);
}
else
{
scanf("%d",&r);
printf("%d\n",query(1,l,r,1,n));
}
}
return 0;
}

2018.7.9

洛谷 P3797 妖梦斩木棒 解题报告的更多相关文章

  1. 洛谷P3797 妖梦斩木棒

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

  2. 洛谷 P3797 妖梦斩木棒

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

  3. 洛谷P3799 妖梦拼木棒

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

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

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

  5. Luogu P3797 妖梦斩木棒

    解题思路 用线段树做这个就不用说了吧,但是要维护的东西确实很神奇.在每一个节点上都维护一个$lbkt$,表示这个区间上最靠左的右括号的位置:一个$rbkt$,表示这个区间上最靠右的左括号的位置.还有一 ...

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

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

  7. [Luogu3797] 妖梦斩木棒

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

  8. 洛谷 P2323 [HNOI2006]公路修建问题 解题报告

    P2323 [HNOI2006]公路修建问题 题目描述 输入输出格式 输入格式: 在实际评测时,将只会有m-1行公路 输出格式: 思路: 二分答案 然后把每条能加的大边都加上,然后加小边 但在洛谷的题 ...

  9. 洛谷 P1852 [国家集训队]跳跳棋 解题报告

    P1852 [国家集训队]跳跳棋 题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在\(a\),\(b\), ...

随机推荐

  1. C++ 学习笔记 变量和基本类型(一)

    C++ 学习笔记 一.变量和基本类型概述 类型是所有程序的基础.类型告诉我们数据代表什么意思以及可以对数据执行哪些操作. c++基本类型: 字符型 整型 浮点型 c++ 还提供了可用于自定义数据类型的 ...

  2. 010 --MySQL查询优化器的局限性

    MySQL的万能"嵌套循环"并不是对每种查询都是最优的.不过还好,mysql查询优化器只对少部分查询不适用,而且我们往往可以通过改写查询让mysql高效的完成工作.在这我们先来看看 ...

  3. SQL Operations Studio的安装和使用

    之前管理和访问SQL SERVER使用的自然是SSMS,功能确实很强大的一个数据库图形化管理软件,但是SSMS有个问题就是体积超级大,启动速度也就比较慢.今天我正好要学习一些T-SQL的内容,在微软的 ...

  4. Spring Data REST PATCH请求远程代码执行漏洞(CVE-2017-8046) 本地复现方法

      #1背景 Spring Data REST是Spring Data项目的一部分,可以轻松地在Spring Data存储库之上构建超媒体驱动的REST Web服务. 恶意的PATCH请求使用精心构造 ...

  5. tty命令详解

    基础命令学习目录首页 原文链接:http://blog.chinaunix.net/uid-9525959-id-2001836.html [功能]  打印连接到标准输入的终端的文件名. [描述]  ...

  6. django_models_Meta字段详解

    Django模型类的Meta是一个内部类,它用于定义一些Django模型类的行为特性.而可用的选项大致包含以下几类 abstract 这个属性是定义当前的模型是不是一个抽象类.所谓抽象类是不会对应数据 ...

  7. webpack入门指南-step04

    一.建立项目 建一个文件夹,然后新建一个package.json的文件在项目根目录下 如果你使用git管理你的这个项目的话,建议你新建一个.gitignore文件,不要让git提交一些node依赖的模 ...

  8. 【欢迎来怼】 Beta发布事后诸葛亮会议

    队名:欢迎来怼 项目名称:博客园Android端APP 小组成员队长:田继平成员:李圆圆,葛美义,王伟东,姜珊,邵朔,阚博文 ————————————————————————————————————— ...

  9. Alpha版本BUG BASH

    在本次软件开发的第一轮迭代中,我们团队遇到了很多问题.首先是和学长联系不上导致拿到项目前一版本的代码的时间延后了一个星期. 拿到代码后发现由于安装环境的问题代码无法移植.在这一阶段我们就耗费了大量的时 ...

  10. Daily Srum 10.30

    Android那一组打算用SQL Server这个关系型数据库,而王鹿鸣他们一组却是依赖于Hbase,这是一件很麻烦的事,所以我打算在这两方面都建立一个数据库.虽然挺麻烦,但是还是为了扩展性所做的必要 ...