zoukankan      html  css  js  c++  java
  • 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。

    Solution

    维护三个堆。

    $h1[x]$存当前重心$x$管辖的范围内的点到$x$在点分树上的父亲的所有距离。

    $h2[x]$存$x$在点分树上所有儿子的$h1$堆的堆顶。

    $h3$存每个点的答案。

    关灯的点$h2$自带一个$0$方便处理单链……

    反正快退役了也不想写太多了……还有问题看代码吧……

    Code

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<queue>
      5 #define N (100009)
      6 using namespace std;
      7 
      8 struct Heap
      9 {
     10     priority_queue<int>q,del;
     11     void push(int x) {q.push(x);}
     12     void erase(int x) {del.push(x);}
     13     bool empty() {return q.size()-del.size()==0;}
     14     int size() {return q.size()-del.size();}
     15     int top()
     16     {
     17         while (!del.empty() && q.top()==del.top()) q.pop(), del.pop();
     18         return q.top();
     19     }
     20     void pop()
     21     {
     22         while (!del.empty() && q.top()==del.top()) q.pop(), del.pop();
     23         return q.pop();
     24     }
     25     int sec()
     26     {
     27         if (size()<2) return -1;
     28         int tmp1=top(); pop();
     29         int tmp2=top(); push(tmp1);
     30         return tmp2;
     31     }
     32 }h1[N],h2[N],h3;
     33 
     34 struct Edge{int to,next;}edge[N<<1];
     35 int n,m,root,sum,light_num;
     36 int s[N],f[N][17],fa[N],dep[N],maxsize[N],size[N],vis[N];
     37 int head[N],num_edge;
     38 
     39 inline int read()
     40 {
     41     int x=0,w=1; char c=getchar();
     42     while (c<'0' || c>'9') {if (c=='-') w=-1; c=getchar();}
     43     while (c>='0' && c<='9') x=x*10+c-'0', c=getchar();
     44     return x*w;
     45 }
     46 
     47 void add(int u,int v)
     48 {
     49     edge[++num_edge].to=v;
     50     edge[num_edge].next=head[u];
     51     head[u]=num_edge;
     52 }
     53 
     54 void DFS(int x,int fa)
     55 {
     56     dep[x]=dep[fa]+1; f[x][0]=fa;
     57     for (int i=1; i<=16; ++i) f[x][i]=f[f[x][i-1]][i-1];
     58     for (int i=head[x]; i; i=edge[i].next)
     59         if (edge[i].to!=fa) DFS(edge[i].to,x);
     60 }
     61 
     62 void Get_Root(int x,int fa)
     63 {
     64     size[x]=1; maxsize[x]=0;
     65     for (int i=head[x]; i; i=edge[i].next)
     66         if (!vis[edge[i].to] && edge[i].to!=fa)
     67         {
     68             Get_Root(edge[i].to,x);
     69             size[x]+=size[edge[i].to];
     70             maxsize[x]=max(maxsize[x], size[edge[i].to]);
     71         }
     72     maxsize[x]=max(maxsize[x],sum-size[x]);
     73     if (maxsize[x]<maxsize[root]) root=x;
     74 }
     75 
     76 void Solve(int x)
     77 {
     78     vis[x]=1;
     79     for (int i=head[x]; i; i=edge[i].next)
     80         if (!vis[edge[i].to])
     81         {
     82             sum=size[edge[i].to]; root=0;
     83             Get_Root(edge[i].to,x);
     84             fa[root]=x; Solve(root);
     85         }
     86 }
     87 
     88 int LCA(int x,int y)
     89 {
     90     if (dep[x]<dep[y]) swap(x,y);
     91     for (int i=16; i>=0; --i)
     92         if (dep[f[x][i]]>=dep[y]) x=f[x][i];
     93     if (x==y) return x;
     94     for (int i=16; i>=0; --i)
     95         if (f[x][i]!=f[y][i]) x=f[x][i], y=f[y][i];
     96     return f[x][0];
     97 }
     98 
     99 void Insert(int x)
    100 {
    101     if (h2[x].size()>=2)
    102         h3.push(h2[x].top()+h2[x].sec());
    103 }
    104 
    105 
    106 void Delete(int x)
    107 {
    108     if (h2[x].size()>=2)
    109         h3.erase(h2[x].top()+h2[x].sec());
    110 }
    111 
    112 void Turn_off(int x)
    113 {
    114     Delete(x); h2[x].push(0); Insert(x);
    115     light_num--;
    116     for (int t=x,ft=fa[t]; ft; t=fa[t],ft=fa[t])
    117     {
    118         Delete(ft);
    119         if (!h1[t].empty()) h2[ft].erase(h1[t].top());
    120         h1[t].push(dep[x]+dep[ft]-2*dep[LCA(x,ft)]);
    121         h2[ft].push(h1[t].top());
    122         Insert(ft);
    123     }
    124 }
    125 
    126 void Turn_on(int x)
    127 {
    128     Delete(x); h2[x].erase(0); Insert(x);
    129     light_num++;
    130     for (int t=x,ft=fa[t]; ft; t=fa[t],ft=fa[t])
    131     {
    132         Delete(ft);
    133         if (!h1[t].empty()) h2[ft].erase(h1[t].top());
    134         h1[t].erase(dep[x]+dep[ft]-2*dep[LCA(x,ft)]);
    135         if (!h1[t].empty()) h2[ft].push(h1[t].top());
    136         Insert(ft);
    137     }
    138 }
    139 
    140 int main()
    141 {
    142     n=read(); sum=maxsize[0]=n;
    143     for (int i=1; i<=n-1; ++i)
    144     {
    145         int u=read(),v=read();
    146         add(u,v); add(v,u);
    147     }
    148     DFS(1,0);
    149     Get_Root(1,0);
    150     Solve(root);
    151     for (int i=1; i<=n; ++i) Turn_off(i);
    152     light_num=0;
    153     m=read();
    154     while (m--)
    155     {
    156         char opt=getchar();
    157         while (opt!='C' && opt!='G') opt=getchar();
    158         if (opt=='C')
    159         {
    160             int x=read();
    161             if (!s[x]) Turn_on(x);
    162             else Turn_off(x);
    163             s[x]^=1;
    164         }
    165         else
    166         {
    167             if (light_num>=n-1) puts(light_num==n?"-1":"0");
    168             else printf("%d
    ",h3.top());
    169         }
    170     }
    171 }
  • 相关阅读:
    CSUFT 1002 Robot Navigation
    CSUFT 1003 All Your Base
    Uva 1599 最佳路径
    Uva 10129 单词
    欧拉回路
    Uva 10305 给任务排序
    uva 816 Abbott的复仇
    Uva 1103 古代象形文字
    Uva 10118 免费糖果
    Uva 725 除法
  • 原文地址:https://www.cnblogs.com/refun/p/10644850.html
Copyright © 2011-2022 走看看