码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ1095: [ZJOI2007]Hide 捉迷藏

时间:2015-07-06 17:40:20      阅读:134      评论:0      收藏:0      [点我收藏+]

标签:

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\n",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

 

 

 

BZOJ1095: [ZJOI2007]Hide 捉迷藏

标签:

原文地址:http://www.cnblogs.com/wzj-is-a-juruo/p/4624842.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!