• BZOJ1095: [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

    HINT

    对于100%的数据, N ≤100000, M ≤500000。

    妈妈我终于写完动态树分治了。
    code几乎抄了一遍黄学长的。
    看这篇吧:http://hzwer.com/5247.html
    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #define rep(s,t) for(int i=s;i<=t;i++)
    #define ren for(int i=first[x];i;i=next[i])
    using namespace std;
    inline int read() {
        int x=0,f=1;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    const int maxn=200010;
    struct Heap {
        priority_queue<int> A,del;
        void push(int x) {A.push(x);}
        void erase(int x) {del.push(x);}
        void pop() {
            while(del.size()&&A.top()==del.top()) A.pop(),del.pop();
            A.pop();
        }
        int top() {
            while(del.size()&&A.top()==del.top()) A.pop(),del.pop();
            return !A.size()?0:A.top();
        }
        int size() {return A.size()-del.size();}
        int stop() {
            if(size()<2) return 0;
            int t1=top();pop();
            int t2=top();push(t1);
            return t2;
        }
    }A,B[maxn],C[maxn];
    int n,m,clo[maxn],first[maxn],next[maxn],to[maxn],es;
    void AddEdge(int u,int v) {
        to[++es]=v;next[es]=first[u];first[u]=es;
        to[++es]=u;next[es]=first[v];first[v]=es;
    }
    int Log[maxn],mn[19][maxn],dep[maxn],pos[maxn],dfs_clock;
    void dfs(int x,int fa) {
        mn[0][++dfs_clock]=dep[x];pos[x]=dfs_clock;
        ren if(to[i]!=fa) {
            dep[to[i]]=dep[x]+1;
            dfs(to[i],x);
            mn[0][++dfs_clock]=dep[x];
        }
    }
    void init() {
        Log[0]=-1;rep(1,200000) Log[i]=Log[i>>1]+1;
        for(int i=1;(1<<i)<=dfs_clock;i++)
           for(int j=1;j+(1<<i)-1<=dfs_clock;j++)
              mn[i][j]=min(mn[i-1][j],mn[i-1][j+(1<<(i-1))]);
    }
    int dist(int x,int y) {
        int ans=dep[x]+dep[y];
        x=pos[x];y=pos[y];if(x>y) swap(x,y);
        int k=Log[y-x+1];
        return ans-2*min(mn[k][x],mn[k][y-(1<<k)+1]);
    }
    int root,size,vis[maxn],f[maxn],s[maxn];
    void getroot(int x,int fa) {
        int maxs=0;s[x]=1;
        ren if(to[i]!=fa&&!vis[to[i]]) getroot(to[i],x),maxs=max(maxs,s[to[i]]),s[x]+=s[to[i]];
        f[x]=max(maxs,size-s[x]);
        if(f[root]>f[x]) root=x;
    }
    int fa[maxn];
    void solve(int x,int F) {
        fa[x]=F;vis[x]=1;
        ren if(!vis[to[i]]) {
            size=f[0]=s[to[i]];getroot(to[i],root=0);
            solve(root,x);
        }
    }
    void turn_off(int u,int v) {
        if(u==v) {
            B[u].push(0);
            if(B[u].size()==2) A.push(B[u].top());
        }
        if(!fa[u]) return;
        int f=fa[u],D=dist(f,v),tmp=C[u].top();C[u].push(D);
        if(D>tmp) {
            int mx=B[f].top()+B[f].stop(),size=B[f].size();
            if(tmp) B[f].erase(tmp);
            B[f].push(D);
            int now=B[f].top()+B[f].stop();
            if(now>mx) {
                if(size>=2) A.erase(mx);
                if(B[f].size()>=2) A.push(now);
            }
        }
        turn_off(f,v);
    }
    void turn_on(int u,int v) {
        if(u==v) {
            if(B[u].size()==2) A.erase(B[u].top());
            B[u].erase(0);
        }
        if(!fa[u]) return;
        int f=fa[u],D=dist(f,v),tmp=C[u].top();
        C[u].erase(D);
        if(D==tmp) {
            int mx=B[f].top()+B[f].stop(),size=B[f].size();
            B[f].erase(D);
            if(C[u].top()) B[f].push(C[u].top());
            int now=B[f].top()+B[f].stop();
            if(now<mx) {
                if(size>=2) A.erase(mx);
                if(B[f].size()>=2) A.push(now);
            }
        }
        turn_on(f,v);
    }
    int main() {
        n=read();
        rep(2,n) AddEdge(read(),read());
        dfs(1,0);init();
        size=f[0]=n;getroot(1,root=0);
        solve(root,0);
        rep(1,n) clo[i]=1,C[i].push(0),turn_off(i,i);
        char ch[2];
        m=read();int cnt=n;
        while(m--) {
            scanf("%s",ch);
            if(ch[0]=='G') printf("%d
    ",cnt<2?-1:A.top());
            else {
                int x=read();
                if(clo[x]) turn_on(x,x),cnt--;
                else turn_off(x,x),cnt++;
                clo[x]^=1;
            }
        }
        return 0;
    }
    View Code
     
  • 相关阅读:
    【扫盲】模块 库 框架 包
    AJax和JQ的结合使用
    AJax的三种响应
    使用session存储数据
    Requset作用域
    Cookie实现记住密码代码
    Cookie技术
    请求转发和重定向
    重定向的两次请求分别是????
    servlet
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/4624842.html
Copyright © 2020-2023  润新知