• 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 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
    ");continue;}
                y=siz[find(x)];
                printf("%d
    ",y);    
            }
        }
        return 0;    
    }
  • 相关阅读:
    无废话XML阅读笔记(三)
    ____ To All Girls & Boys
    FDT注册码
    无废话XML阅读笔记(五)
    无废话XML阅读笔记(一)
    物理运动学公式汇总
    flash编译器错误查询表
    入秋了,给大家一些生活小常识
    12年
    linux 自动上传程序
  • 原文地址:https://www.cnblogs.com/five20/p/9791893.html
Copyright © 2020-2023  润新知