1. 程式人生 > >洛谷P3797 妖夢斬木棒

洛谷P3797 妖夢斬木棒

node code freopen 輸入輸出格式 printf bool int 這樣的 輸出格式

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

/*
    線段樹維護一段區間向左有沒有開口,向右有沒有開口,以及是否貫通(全是X),包含幾段完整木棒
    如XXX)XXX,就只有向左開口,沒有向右開口
    然後單點修改,區間查詢即可。
    與普通線段樹的區別就在於多了合並操作 
*/ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n,m; struct node{ int num; bool l,r,p; node(){} node(int l_,int r_,int p_){ l=l_;r=r_;p=p_;num=0; } }tr[800011]; node merge(node a,node b){ node res; res.p=a.p&b.p; res.l=a.p?b.l:a.l; res.r=b.p?a.r:b.r; res.num=a.num+b.num; if(a.r&&b.l&&!a.p&&!b.p)res.num++; return res; } void pushup(int k){ tr[k]=merge(tr[k<<1],tr[k<<1|1]); } node query(int k,int l,int r,int L,int R){ if(l>=L&&r<=R)return tr[k]; int mid=(l+r)>>1; if(mid+1>R)return query(k<<1,l,mid,L,R); if(L>mid)return query(k<<1|1,mid+1,r,L,R); return merge(query(k<<1,l,mid,L,R),query(k<<1|1,mid+1,r,L,R)); } void build(int l,int r,int k){ if(l==r){ if(l==1)tr[k]=node(0,1,0); else if(l==n)tr[k]=node(1,0,0); else tr[k]=node(1,1,1); tr[k].num=0; return; } int mid=(l+r)>>1; build(l,mid,k<<1); build(mid+1,r,k<<1|1); pushup(k); } void modify(int k,int l,int r,int x,int type){ if(l==r){ if(type==0)tr[k]=node(1,0,0); else if(type==1)tr[k]=node(0,1,0); else tr[k]=node(1,1,1); return; } int mid=(l+r)>>1; if(x<=mid)modify(k<<1,l,mid,x,type); else modify(k<<1|1,mid+1,r,x,type); pushup(k); } int main(){ freopen("Cola.txt","r",stdin); scanf("%d%d",&n,&m); build(1,n,1); while(m--){ int type; scanf("%d",&type); if(type==1){ int x,t;char c; scanf("%d %c",&x,&c); if(c==X)t=2; else if(c==))t=0; else t=1; modify(1,1,n,x,t); } else { int l,r; scanf("%d%d",&l,&r); printf("%d\n",query(1,1,n,l,r).num); } } return 0; }

洛谷P3797 妖夢斬木棒