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 }
  • 相关阅读:
    Eclipse 的SVN 插件
    linux克隆后修配置
    SVN服务器端环境搭建步骤
    Linux安装 jdk、tomcat、eclipse、mysql
    Linux RPM和YUM
    linux进程管理
    day21
    day20
    day18 作业
    day 19
  • 原文地址:https://www.cnblogs.com/refun/p/10644850.html
Copyright © 2011-2022 走看看