• [bzoj1095][ZJOI2007]Hide 捉迷藏 点分树,动态点分治


    【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。

    C.每个重心存所有子树到其距离
    B.每个重心存各个子树最大值,即子结点堆C的最大值
    A.全局一个堆,维护答案最大值,存每个堆B的最大值和次大值之和
     
     
     
    C的意思是u这个节点,经过u,到达其父亲f的路径的所有距离,
    B是维护所有的子节点的C的最大值,
    A是维护各个B中的最大值。
     
    动态点分治是树上动态添加节点,在这种情况下动态维护点分树的结构
     
    这道题目的树的结构是不变的,所以建出点分树即可,
    然后维护各个堆的值即可。
     
    因为点分树上是log层的,堆维护也是log的,所有每次询问logn
    修改logn logn,所有总复杂度是n log^2n
     
    计算深度那里十分巧妙,用一个rmq记录,就是通过dfs访问顺序,然后进入一个点记录一次,
    这样总共均摊是2*n,和边有关系,
    然后rmq记录最小值,发现这个就是lca的深度
    然后距离就比较好算了,O(1)算出,
     
      1 #include<cstring>
      2 #include<cmath>
      3 #include<iostream>
      4 #include<cstdio>
      5 #include<algorithm>
      6 #include<queue>
      7 
      8 #define inf 1000000007
      9 #define N 200007
     10 #define ll long long
     11 using namespace std;
     12 inline int read()
     13 {
     14     int x=0,f=1;char ch=getchar();
     15     while(ch<'0'||ch>'9'){if (ch=='-')f=-1;ch=getchar();}
     16     while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
     17     return x*f;
     18 }
     19 
     20 int n,m,rt,dfn,sum,tot;
     21 int bin[22],Log[N];
     22 int siz[N],f[N],dep[N];
     23 int cnt,hed[N],rea[N],nxt[N];
     24 int mn[19][N],pos[N],fa[N];
     25 bool vis[N],clo[N];
     26 struct heap
     27 {
     28     priority_queue<int> A,B;
     29     void push(int x){A.push(x);}
     30     void erase(int x){B.push(x);}
     31     void pop()
     32     {
     33         while(B.size()&&A.top()==B.top())
     34             A.pop(),B.pop();
     35         A.pop();
     36     }
     37     int top()
     38     {
     39         while(B.size()&&A.top()==B.top())
     40             A.pop(),B.pop();
     41         if(!A.size())return 0;
     42         return A.top();
     43     }
     44     int size(){return A.size()-B.size();}
     45     int stop()
     46     {
     47         if(size()<2)return 0;
     48         int x=top();pop();
     49         int y=top();push(x);
     50         return y;
     51     }
     52 }A,B[100005],C[100005];
     53 
     54 void add(int u,int v)
     55 {
     56     nxt[++cnt]=hed[u];
     57     hed[u]=cnt;
     58     rea[cnt]=v;
     59 }
     60 void dfs(int u,int fa)
     61 {
     62     mn[0][++dfn]=dep[u],pos[u]=dfn;
     63     for (int i=hed[u];i!=-1;i=nxt[i])
     64     {
     65         int v=rea[i];
     66         if (v==fa)continue;
     67         dep[v]=dep[u]+1;
     68         dfs(v,u);
     69         mn[0][++dfn]=dep[u];
     70     }
     71 }
     72 void get_root(int u,int fa)
     73 {
     74     siz[u]=1,f[u]=0;
     75     for (int i=hed[u];i!=-1;i=nxt[i])
     76     {
     77         int v=rea[i];
     78         if (v==fa||vis[v])continue;
     79         get_root(v,u);
     80         siz[u]+=siz[v];
     81         f[u]=max(f[u],siz[v]);
     82     }
     83     f[u]=max(f[u],sum-siz[u]);
     84     if (f[u]<f[rt])rt=u;
     85 }
     86 void divide(int u,int par)
     87 {
     88     fa[u]=par,vis[u]=1;int sums=sum;
     89     for (int i=hed[u];i!=-1;i=nxt[i])
     90     {
     91         int v=rea[i];
     92         if (vis[v])continue;
     93         if (siz[v]>siz[u]) sum=sums-siz[u];
     94         else sum=siz[v];
     95         rt=0;
     96         get_root(v,u);
     97         divide(rt,u);
     98     }
     99 }
    100 int rmq(int x,int y)
    101 {
    102     x=pos[x],y=pos[y];
    103     if (y<x)swap(x,y);
    104     int t=Log[y-x+1];
    105     return min(mn[t][x],mn[t][y-bin[t]+1]);
    106 }
    107 int dis(int x,int y)
    108 {
    109     return dep[x]+dep[y]-2*rmq(x,y);
    110 }
    111 void turn_off(int u,int v)
    112 {
    113     if (u==v)
    114     {
    115         B[u].push(0);
    116         if (B[u].size()==2)A.push(B[u].top());
    117     }
    118     if(!fa[u])return;
    119     int f=fa[u],D=dis(f,v),tmp=C[u].top();
    120     C[u].push(D);
    121     if (D>tmp)
    122     {
    123         int mx=B[f].top()+B[f].stop(),size=B[f].size();
    124         if (tmp)B[f].erase(tmp);
    125         B[f].push(D);
    126         int now=B[f].top()+B[f].stop();
    127         if(now>mx)
    128         {
    129             if (size>=2)A.erase(mx);
    130             if (B[f].size()>=2)A.push(now);
    131         }
    132     }
    133     turn_off(f,v);
    134 }
    135 void turn_on(int u,int v)
    136 {
    137     if(u==v)
    138     {
    139         if(B[u].size()==2)A.erase(B[u].top());
    140         B[u].erase(0);
    141     }
    142     if(!fa[u])return;
    143     int f=fa[u],D=dis(f,v),tmp=C[u].top();
    144     C[u].erase(D);
    145     if(D==tmp)
    146     {
    147         int mx=B[f].top()+B[f].stop(),size=B[f].size();
    148         B[f].erase(D);
    149         if(C[u].top())B[f].push(C[u].top());
    150         int now=B[f].top()+B[f].stop();
    151         if(now<mx)
    152         {
    153             if(size>=2)A.erase(mx);
    154             if(B[f].size()>=2)A.push(now);
    155         }
    156     }
    157     turn_on(f,v);
    158 }
    159 int main()
    160 {
    161     bin[0]=1;for (int i=1;i<20;i++)bin[i]=bin[i-1]<<1;//2的幂次
    162     Log[0]=-1;for (int i=1;i<=200000;i++)Log[i]=Log[i>>1]+1;
    163     n=read();memset(hed,-1,sizeof(hed));
    164     for(int i=1;i<n;i++)
    165     {
    166         int u=read(),v=read();
    167         add(u,v),add(v,u);
    168     }
    169     
    170     dfs(1,0);//预处理出深度
    171     
    172     for (int i=1;i<=Log[dfn];i++)
    173         for (int j=1;j<=dfn;j++)
    174             if (j+bin[i]-1<=dfn) mn[i][j]=min(mn[i-1][j],mn[i-1][j+bin[i-1]]);
    175     //预处理,处理出向下走2^x步的到达最浅的点,就是起lca的深度。
    176 
    177     rt=0,f[0]=inf,sum=n;
    178     get_root(1,0),divide(rt,0);
    179     for (int i=1;i<=n;i++)
    180         clo[i]=true;
    181     for (int i=1;i<=n;i++)turn_off(i,i);
    182     tot=n;//tot记录当前多少灯是灭的。
    183 //    printf("%d
    ",A.top());
    184 
    185     char ch[2];m=read();
    186     while(m--)
    187     {
    188         scanf("%s",ch+1);
    189         if (ch[1]=='G')
    190         {
    191             if (tot<=1) printf("%d
    ",tot-1);
    192             else printf("%d
    ",A.top());
    193         }
    194         else
    195         {
    196             int x=read();
    197             if (clo[x])turn_on(x,x),tot--;
    198             else turn_off(x,x),tot++;
    199             clo[x]^=1;
    200         }
    201     }
    202 }
     
     
     
  • 相关阅读:
    Antenna Placement---poj3020(最大匹配)
    Strategic Game--hdu1054(最小覆盖点)
    Oil Skimming---hdu4185(最大匹配)
    Windows平台下NS2网络仿真环境的搭建
    视频参数(流媒体系统,封装格式,视频编码,音频编码,播放器)对比
    最简单的基于FFMPEG+SDL的音频播放器
    FFplay源代码分析:整体流程图
    图解FFMPEG打开媒体的函数avformat_open_input
    100行代码实现最简单的基于FFMPEG+SDL的视频播放器
    视频编码标准汇总及比较
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8250931.html
Copyright © 2020-2023  润新知