打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
P1503 鬼子进村

题目背景

小卡正在新家的客厅中看电视。电视里正在播放放了千八百次依旧重播的《亮剑》,剧中李云龙带领的独立团在一个县城遇到了一个鬼子小队,于是独立团与鬼子展开游击战。

题目描述

描述 县城里有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 9D 3D 6D 5Q 4Q 5RQ 4RQ 4
输出样例#1: 
1024

说明

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

 

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;    }

 

来源:http://www.icode9.com/content-4-54101.html
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
NOIP 2017提高组复赛解题报告
[JLOI2015] 城池攻占
树链剖分
「NOTE」可持久化非旋Treap
树链剖分详解及模板
树链剖分解析
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服