博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
妖梦斩木棒
阅读量:5078 次
发布时间:2019-06-12

本文共 3051 字,大约阅读时间需要 10 分钟。

题目背景

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

题目描述

有一天,妖梦正在练习剑术。地面上摆放了一支非常长的木棒,妖梦把它们切成了等长的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,输出一行一个整数,表示对应询问的答案。

 

输入输出样例

输入样例#1:
4 42 1 42 2 41 2 (2 2 4
输出样例#1:
101

说明

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

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

by-orangebird

线段树

对于每一个区间,维护是否向左开c[rt].ls(右括号左边无木棍),是否向右开c[rt].rs(左括号右边无棍)

再维护是否为空c[rt].ps(用处:合并时,c[rt*2].ps&&c[rt*2+1].ls→c[rt].ls=1)

还维护完整木棍数才c[rt].sum;合并时c[rt*2].rs&&c[rt*2+1].ls→c[rt].sum=c[rt*2].sum+c[rt*2+1].sum+1;

注意查询时,不能直接返回c[rt].sum并求和。因为会多算或少算。要返回所有维护信息,再把解合并

如查询1-7(红色为返回c[rt].sum的节点),ans=1,但明显ans应等于2,应为返回时忽略了左右单独括号的合并

                    (xx)()(xx)

              (xx)(              )(xx)

                                  )(x     x)   

#include
#include
#include
#include
using namespace std;struct Messi{ int ls,rs,sum,ps;}c[800001];int n,m;Messi merge(Messi a,Messi b){ Messi x; x.ps=a.ps&b.ps; x.ls=a.ps?b.ls:a.ls; x.rs=b.ps?a.rs:b.rs; x.sum=a.sum+b.sum; if (b.ls&&a.rs&&!b.ps&&!a.ps) x.sum++; return x;}void build(int rt,int l,int r){ if (l==r) { if (l==1) { c[rt].rs=1; c[rt].ps=0; c[rt].ls=0; } else if (r==n) { c[rt].rs=0; c[rt].ps=0; c[rt].ls=1; } else { c[rt].rs=1; c[rt].ls=1; c[rt].ps=1; } return; } int mid=(l+r)/2; build(rt*2,l,mid); build(rt*2+1,mid+1,r); c[rt]=merge(c[rt*2],c[rt*2+1]);}void update(int rt,int l,int r,int x,int sign){ if (l==r) { if (sign==1) { c[rt].rs=1; c[rt].ps=0; c[rt].ls=0; } else if (sign==0) { c[rt].rs=0; c[rt].ps=0; c[rt].ls=1; } else { c[rt].rs=1; c[rt].ls=1; c[rt].ps=1; } return; } int mid=(l+r)/2; if (x<=mid) update(rt*2,l,mid,x,sign); else update(rt*2+1,mid+1,r,x,sign); c[rt]=merge(c[rt*2],c[rt*2+1]);}Messi query(int rt,int l,int r,int L,int R){ if (l>=L&&r<=R) { return c[rt]; } int mid=(l+r)/2; if (R<=mid) return query(rt*2,l,mid,L,R); if (L>mid) return query(rt*2+1,mid+1,r,L,R); return merge(query(rt*2,l,mid,L,R),query(rt*2+1,mid+1,r,L,R));}int main(){
int i,j,k,x,y;char ch; cin>>n>>m; build(1,1,n); for (i=1;i<=m;i++) { scanf("%d",&k); if (k==2) { scanf("%d%d",&x,&y); //cout<<'p'<
<<' '<
<

 

转载于:https://www.cnblogs.com/Y-E-T-I/p/7041607.html

你可能感兴趣的文章
Mongo自动备份
查看>>
cer证书签名验证
查看>>
新手Python第一天(接触)
查看>>
【bzoj1029】[JSOI2007]建筑抢修
查看>>
synchronized
查看>>
codevs 1080 线段树练习
查看>>
[No0000195]NoSQL还是SQL?这一篇讲清楚
查看>>
【深度学习】caffe 中的一些参数介绍
查看>>
Python-Web框架的本质
查看>>
QML学习笔记之一
查看>>
Window 的引导过程
查看>>
App右上角数字
查看>>
从.NET中委托写法的演变谈开去(上):委托与匿名方法
查看>>
小算法
查看>>
201521123024 《java程序设计》 第12周学习总结
查看>>
新作《ASP.NET MVC 5框架揭秘》正式出版
查看>>
IdentityServer4-用EF配置Client(一)
查看>>
WPF中实现多选ComboBox控件
查看>>
读构建之法第四章第十七章有感
查看>>
Windows Phone开发(4):框架和页 转:http://blog.csdn.net/tcjiaan/article/details/7263146
查看>>