• bzoj:1095: [ZJOI2007]Hide 捉迷藏


    Description

      捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子。某天,Jiajia、Wind和孩子们决定在家里玩
    捉迷藏游戏。他们的家很大且构造很奇特,由N个屋子和N-1条双向走廊组成,这N-1条走廊的分布使得任意两个屋
    子都互相可达。游戏是这样进行的,孩子们负责躲藏,Jiajia负责找,而Wind负责操纵这N个屋子的灯。在起初的
    时候,所有的灯都没有被打开。每一次,孩子们只会躲藏在没有开灯的房间中,但是为了增加刺激性,孩子们会要
    求打开某个房间的电灯或者关闭某个房间的电灯。为了评估某一次游戏的复杂性,Jiajia希望知道可能的最远的两
    个孩子的距离(即最远的两个关灯房间的距离)。 我们将以如下形式定义每一种操作: C(hange) i 改变第i个房
    间的照明状态,若原来打开,则关闭;若原来关闭,则打开。 G(ame) 开始一次游戏,查询最远的两个关灯房间的
    距离。

    Input

      第一行包含一个整数N,表示房间的个数,房间将被编号为1,2,3…N的整数。接下来N-1行每行两个整数a, b,
    表示房间a与房间b之间有一条走廊相连。接下来一行包含一个整数Q,表示操作次数。接着Q行,每行一个操作,如
    上文所示。

    Output

      对于每一个操作Game,输出一个非负整数到hide.out,表示最远的两个关灯房间的距离。若只有一个房间是关
    着灯的,输出0;若所有房间的灯都开着,输出-1。

    Sample Input

    8
    1 2
    2 3
    3 4
    3 5
    3 6
    6 7
    6 8
    7
    G
    C 1
    G
    C 2
    G
    C 1
    G

    Sample Output

    4
    3
    3
    4

    写的时候感觉脑子要炸了……代码会很丑……

    是正常三层堆的做法。

    #include<queue>
    #include<cstdio>
    #include<algorithm>
    #define MN 100001
    using namespace std;
    int read_p,read_ca;
    inline int read(){
        read_p=0;read_ca=getchar();
        while(read_ca<'0'||read_ca>'9') read_ca=getchar();
        while(read_ca>='0'&&read_ca<='9') read_p=read_p*10+read_ca-48,read_ca=getchar();
        return read_p;
    }
    struct na{
        int x,y,z,ne;
    }b[2*MN],bb[1700001],bv[MN];
    int n,m,ma,la[MN],num=0,fa[MN],s[MN],lla[MN],vla[MN],size,root,nnum=0,vnum=0,mmh,ha[MN],ppp=0,nm=0;
    bool v[MN],p[MN];
    struct nma{
        int x,fr;
        bool operator < (nma a)const{return x<a.x;}
    };
    nma m_a(int x,int fr){nma a;a.x=x;a.fr=fr;return a;}
    const int INF=1e9;
    priority_queue <nma> q[MN],qv[MN],all;
    inline void in(int x,int y){b[++num].y=y;b[num].ne=la[x];la[x]=num;}
    inline void add(int u,int x,int y,int z){bb[++nnum].x=x;bb[nnum].y=y;bb[nnum].z=z;bb[nnum].ne=lla[u];lla[u]=nnum;}
    inline void newin(int x,int y){bv[++vnum].y=y;bv[vnum].ne=vla[x];vla[x]=vnum;}
    inline void gs(int x,int f){
        int u=0;s[x]=1;
        for (int i=la[x];i;i=b[i].ne)
        if (!v[b[i].y]&&b[i].y!=f) gs(b[i].y,x),s[x]+=s[b[i].y],u=u>s[b[i].y]?u:s[b[i].y];
        if (u<size-s[x]) u=size-s[x];
        if (u<ma) root=x,ma=u;
    }
    inline void ch(int x){
        for (int i=vla[x];i;i=bv[i].ne) if (!q[bv[i].y].empty())qv[x].push(m_a(q[bv[i].y].top().x,bv[i].y));
    }
    inline void cg(int x){
        while(!qv[x].empty()){if (!q[qv[x].top().fr].empty()) if (qv[x].top().x==q[qv[x].top().fr].top().x) break;qv[x].pop();}
        if (qv[x].empty()){ha[x]=-1;return;}
        nma mmh=qv[x].top();int u=mmh.x;
        qv[x].pop();
        while(!qv[x].empty()){if (qv[x].top().fr!=mmh.fr)if (!q[qv[x].top().fr].empty()) if (qv[x].top().x==q[qv[x].top().fr].top().x) break;qv[x].pop();}
        if (qv[x].empty()){if (!p[x]) {ha[x]=-1;qv[x].push(mmh);return;}}else u+=qv[x].top().x;
        qv[x].push(mmh);
        ha[x]=u;
        all.push(m_a(u,x));
        while(!all.empty()){if (all.top().x==ha[all.top().fr]) break;all.pop();}
    }
    inline void gx(int x,int y){
        mmh=q[x].top().x;
        while(!q[x].empty()){if (p[q[x].top().fr]) break;q[x].pop();}
        if (!q[x].empty()) if (q[x].top().x!=mmh) qv[y].push(m_a(q[x].top().x,x));
        while(!qv[y].empty()){if (!q[qv[y].top().fr].empty()) if (qv[y].top().x==q[qv[y].top().fr].top().x) break;qv[y].pop();}
    }
    inline void dfs(int x,int f,int dis){
        if (dis==1) mmh=++nm,newin(root,nm);
        if (f) add(x,mmh,root,dis),q[mmh].push(m_a(dis,x));
        for (int i=la[x];i;i=b[i].ne)
        if (b[i].y!=f&&(!v[b[i].y])) dfs(b[i].y,x,dis+1);
    }
    inline void work(int x,int siz,int f){
        size=siz;ma=INF;gs(x,0);x=root;
        dfs(x,0,0);ha[x]=-1;ch(x);cg(x);v[x]=1;
        for (int i=la[x];i;i=b[i].ne)
        if (!v[b[i].y]) work(b[i].y,s[b[i].y],x);
    }
    inline int min(int x,int y){return x>y?y:x;}
    char cc[10];
    int main(){
        //freopen("a.in","r",stdin);
        //freopen("a.out","w",stdout);
        int x,y;register int j;
        ppp=n=read();
        for (int i=1;i<n;i++) x=read(),y=read(),in(x,y),in(y,x);
        for (int i=1;i<=n;i++) p[i]=1;
        work(1,n,0);
        n=read();
        while(n--){
            scanf("%s",cc);
            if (cc[0]=='C'){
                if (p[y=read()]^=1)
                for (j=lla[y];j;j=bb[j].ne){
                    if (q[bb[j].x].empty()) mmh=-1;else mmh=q[bb[j].x].top().x;
                    q[bb[j].x].push(m_a(bb[j].z,y));
                    while(!q[x].empty()){if (p[q[x].top().fr]) break;q[x].pop();}
                    if (q[bb[j].x].top().x!=mmh) qv[bb[j].y].push(m_a(q[bb[j].x].top().x,bb[j].x)),cg(bb[j].y);
                }else for (j=lla[y];j;j=bb[j].ne) gx(bb[j].x,bb[j].y),cg(bb[j].y);cg(y);
                if (p[y]) ppp++;else ppp--;
            }
            else if (!ppp)printf("-1
    ");else if (ppp==1) printf("0
    ");else{
                while(!all.empty()){if (all.top().x==ha[all.top().fr]) break;all.pop();}
                printf("%d
    ",all.top().x);
            }
        }
    }
    View Code
  • 相关阅读:
    使用Picture Control显示BMP图片
    [转]程序员技术练级攻略
    自绘控件笔记
    VS2010中CMFCToolBar的用法
    我用到的FireFox浏览器插件
    C# 中的 DataTimePicker 控件的时间转换
    MacBook 小白,安装 JDK
    C# Combobox 设置选中项
    Drupal7(2)
    Drupal7(1)
  • 原文地址:https://www.cnblogs.com/Enceladus/p/5414591.html
Copyright © 2020-2023  润新知