1. 程式人生 > >P1503 鬼子進村

P1503 鬼子進村

article lse char har pac sin 左右 main strong

題目背景

小卡正在新家的客廳中看電視。電視裏正在播放放了千八百次依舊重播的《亮劍》,劇中李雲龍帶領的獨立團在一個縣城遇到了一個鬼子小隊,於是獨立團與鬼子展開遊擊戰。

題目描述

描述 縣城裏有n個用地道相連的房子,第i個只與第i-1和第i+1個相連。這是有m個消息依次傳來

1、消息為D x:鬼子將x號房子摧毀了,地道被堵上。

2、消息為R :村民們將鬼子上一個摧毀的房子修復了。

3、消息為Q x:有一名士兵被圍堵在x號房子中。

李雲龍收到信息很緊張,他想知道每一個被圍堵的士兵能夠到達的房子有幾個。

輸入輸出格式

輸入格式:

第一行2個整數n,m(n,m<=50000)。

接下來m行,有如題目所說的三種信息共m條。

輸出格式:

對於每一個被圍堵的士兵,輸出該士兵能夠到達的房子數。

輸入輸出樣例

輸入樣例#1:
7 9
D 3
D 6
D 5
Q 4
Q 5
R
Q 4
R
Q 4
輸出樣例#1:
1
0
2
4

說明

若士兵被圍堵在摧毀了的房子中,那只能等死了。。。。。。

Solution:

  本題無旋treap。

  實現過程略為繁瑣,但是思路很簡單:

  初始時該序列就是一棵treap,每刪除一個節點等價於將該節點放到根並分離左右子樹(註意判斷一個節點重復被刪的情況),用棧記錄下每次分離後的兩棵新樹,那麽查詢就是當前節點所在樹的大小,修復節點就是個彈棧合並子樹的過程。  

代碼:

/*Code by 520 -- 10.3*/
#include<bits/stdc++.h>
#define il inline
#define ll long long
#define RE register
#define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++)
#define Bor(i,a,b) for(RE int (i)=(b);(i)>=(a);(i)--)
using namespace std;
const int N=100005;
int n,m,stk[N],top,lsx[N],lsy[N];
bool vis[N]; int cnt,root,siz[N],ch[N][2],fa[N],date[N],rnd[N]; il int newnode(int v){siz[++cnt]=1,fa[cnt]=0,date[cnt]=v,rnd[cnt]=rand();return cnt;} il void up(int rt){ siz[rt]=siz[ch[rt][0]]+siz[ch[rt][1]]+1; if(ch[rt][0]) fa[ch[rt][0]]=rt; if(ch[rt][1]) fa[ch[rt][1]]=rt; } int merge(int x,int y){ if(!x||!y) return x+y; if(rnd[x]<rnd[y]) {ch[x][1]=merge(ch[x][1],y),up(x);return x;} else {ch[y][0]=merge(x,ch[y][0]),up(y);return y;} } void split(int rt,int v,int &x,int &y){ if(!rt) {x=y=0;return;} if(date[rt]<=v) x=rt,split(ch[rt][1],v,ch[x][1],y),up(x); else y=rt,split(ch[rt][0],v,x,ch[y][0]),up(y); } il void ins(int v){int x=0,y=0;split(root,v,x,y);root=merge(merge(x,newnode(v)),y);} int find(int x){return !fa[x]?x:find(fa[x]);} int main(){ scanf("%d%d",&n,&m); For(i,1,n) ins(i); char opt[2]; int x,y; For(i,1,m){ scanf("%s",opt); if(opt[0]==D) { scanf("%d",&x); stk[++top]=x;vis[x]=1; split(find(x),x,lsx[top],lsy[top]); split(lsx[top],x-1,lsx[top],y); fa[lsx[top]]=0,fa[lsy[top]]=0; } else if(opt[0]==R) merge(merge(lsx[top],stk[top]),lsy[top]),vis[stk[top--]]=0; else { scanf("%d",&x); if(vis[x]) {printf("0\n");continue;} y=siz[find(x)]; printf("%d\n",y); } } return 0; }

P1503 鬼子進村