zoukankan      html  css  js  c++  java
  • [luogu 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,输出一行一个整数,表示对应询问的答案。

    输入输出样例

    输入样例#1:
    4 4
    2 1 4
    2 2 4
    1 2 (
    2 2 4
    输出样例#1:
    1
    0
    1

    说明

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

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

    by-orangebird


    十分可爱的线段树题啊QAQ

    造一棵线段树,维护

            1.有几段完整的木棍,

            2.左边是否有向右边的开口,

            3.右边是否有向左边的开口,

            4.以及是否完全无开口(全为'X')(便于区间合并)。

    区间合并想得有点乱,但是不用下传标记的单点修改还是很exciting的。

    一开始想特判一下n=1的情况来着,后来想想算了吧。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<iostream>
      4 using namespace std;
      5 
      6 inline int rint(){
      7     char ch;
      8     int re=0;
      9     bool flag=0;
     10     while((ch=getchar())!='-'&&(ch<'0'||ch>'9'));
     11     ch=='-'?flag=1:re=ch-'0';
     12     while((ch=getchar())>='0'&&ch<='9')  re=re*10+ch-'0';
     13     return flag?-re:re;
     14 }
     15 
     16 inline char rchar(){
     17     char ch;
     18     while((ch=getchar())!='X'&&ch!='('&&ch!=')');
     19     return ch;
     20 }
     21 
     22 struct segment{
     23     int l,r,num;
     24     bool ll,rr,xx;
     25     segment(){  num=0;  ll=0;  rr=0;  xx=0;  }
     26 };
     27 
     28 const int maxn=200001;
     29 
     30 segment tre[maxn<<2];
     31 int n,m;
     32 
     33 segment merge(const segment &tl,const segment &tr){
     34     segment tx;
     35     tx.l=tl.l;  tx.r=tr.r;
     36     tx.xx=tl.xx&tr.xx;
     37     tx.ll=tr.xx?tl.ll:tr.ll;
     38     tx.rr=tl.xx?tr.rr:tl.rr;
     39     tx.num=tl.num+tr.num+((tl.ll&tr.rr)?1:0);
     40     return tx;
     41 }
     42 
     43 void push_up(int x){
     44     tre[x]=merge(tre[x<<1],tre[x<<1|1]);
     45 }
     46 
     47 void build(int x,int l,int r){
     48     tre[x].l=l;  tre[x].r=r;
     49     if(l==r){
     50         if(l==1)  tre[x].ll=1;
     51         else  if(r==n)  tre[x].rr=1;
     52         else  tre[x].xx=1;
     53         return;
     54     }
     55     int mid=(l+r)>>1;
     56     build(x<<1,l,mid);  build(x<<1|1,mid+1,r);
     57     push_up(x);
     58 }
     59 
     60 void change(int x,int pos,int chaa){
     61     if(tre[x].l==tre[x].r){
     62         if(chaa==0){
     63             tre[x].ll=0;
     64             tre[x].rr=0;
     65             tre[x].xx=1;
     66         }
     67         else  if(chaa==1){
     68             tre[x].ll=1;
     69             tre[x].rr=0;
     70             tre[x].xx=0;
     71         }
     72         else{
     73             tre[x].ll=0;
     74             tre[x].rr=1;
     75             tre[x].xx=0;
     76         }
     77         return;
     78     }
     79     int mid=(tre[x].l+tre[x].r)>>1;
     80     if(pos<=mid)  change(x<<1,pos,chaa);
     81     else  change(x<<1|1,pos,chaa);
     82     push_up(x);
     83 }
     84 
     85 segment query(int x,int L,int R){
     86     if(L<=tre[x].l&&tre[x].r<=R)  return tre[x];
     87     int mid=(tre[x].l+tre[x].r)>>1;
     88     if(R<=mid)  return query(x<<1,L,R);
     89     if(L>mid)  return query(x<<1|1,L,R);
     90     return merge(query(x<<1,L,mid),query(x<<1|1,mid+1,R));
     91 }
     92 
     93 int main(){
     94     //freopen("temp.in","r",stdin);
     95     n=rint();  m=rint();
     96     build(1,1,n);
     97     int opt,pos,left,right,chaa;
     98     char cha;
     99     for(int i=0;i<m;i++){
    100         opt=rint();
    101         switch(opt){
    102             case 1:{
    103                 pos=rint();  cha=rchar();
    104                 if(cha=='X')  chaa=0;
    105                 else  if(cha=='(')  chaa=1;
    106                 else  chaa=2;
    107                 change(1,pos,chaa);
    108                 break;
    109             }
    110             case 2:{
    111                 left=rint();  right=rint();
    112                 printf("%d
    ",query(1,left,right).num);
    113                 break;
    114             }
    115         }
    116     }
    117     return 0;
    118 }

    我听过空境的回音
    雨水浇绿孤山岭
    听过被诅咒的秘密
    没听过你
  • 相关阅读:
    @从零开始实现一个插件化框架(一)
    @从零开始实现一个插件化框架(二)
    @从零开始实现一个插件化框架(三)
    @CoordinatorLayout使用详解: 打造折叠悬浮效果
    Oracle 11g数据库详细安装过程
    web service 的跨语言特性
    struts2--值栈
    事务处理中如何获取同一个connection 对象
    jsp中文乱码问题
    设置工作集
  • 原文地址:https://www.cnblogs.com/ZYBGMZL/p/6971461.html
Copyright © 2011-2022 走看看