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。

     
    我有多久没碰博客了ojz大概是最近太怠惰了吧……
    然后最近在学点分治,Zn_H神犇就唆使我做这道题咯QAQ
    还是太神了看了题解想了好久才懂……
     
    先建一个重心树,这个的意思就是,通过点分治的过程,找到每一个层的重心,然后用这些重心上一层重心连下一层这样建一个树。
    这样可以保证重心树深度小于等于logn。
    然后对于每个点建两个堆,
    第一个堆s1表示:该点的所有子树的点到其重心树上的父亲的距离。
    第二个堆s2表示:该点在重心树上的所有子树的点的堆s1的top值。
    再用一个ans堆记录每个点的堆s2上最大值和次大值之和,询问答案即取top即可。
     
    删除操作和插入操作就对这两个堆进行修改。
    可以这么理解:
    每次修改后我们可以在每次向上更新时,先删去在ans堆的中的目前点的重心树上父亲的s2堆的最大值和次大值之和,再删去目前点的重心树上父亲的s2堆中,目前点的s1堆的top值。然后操作,插入/删除目前点的重心树上父亲到x(操作的那个点)的距离。最后再插入目前点的重心树上父亲的s2堆中,目前点的s1堆的top值,再在ans堆中插入目前点的重心树上父亲的s2堆的最大值和次大值之和。(各种拗口总之看代码其实很好懂)
     
    代码这样QAQ(看有dalao只写了120+行,佩服ojz)
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstdlib>
      4 #include<cstring>
      5 #include<cmath>
      6 #include<queue>
      7 #include<algorithm>
      8 using namespace std;
      9 #define maxm 500005
     10 #define maxn 100100
     11 
     12 int read()
     13 {
     14     int f=1,p=0;
     15     char c=getchar();
     16     while (c<'0'||c>'9'){if (c=='-')f=-1;c=getchar();}
     17     while (c>='0'&&c<='9'){p=p*10+c-'0';c=getchar();}
     18     return f*p;
     19 }
     20 
     21 int n,m,cnt=0,all,rt,T=0,tot=0;
     22 int son[maxn],f[maxn],fa[maxn],pos[maxn],dep[maxn],a[maxn<<1][20];
     23 int lg2[maxn<<1],head[maxn],can[maxn];
     24 bool cdt[maxn];
     25 struct edge{int u,v,next;}e[maxn<<1];
     26 
     27 struct node
     28 {
     29     priority_queue<int> heap,delmark;
     30 
     31     void ins(int x)
     32     {heap.push(x);}
     33     void del(int x)
     34     {delmark.push(x);}
     35     void POP()
     36     {
     37         while (delmark.size()&&delmark.top()==heap.top())
     38         delmark.pop(),heap.pop();
     39         heap.pop();
     40     }
     41     int TOP()
     42     {
     43         while (delmark.size()&&delmark.top()==heap.top())
     44         delmark.pop(),heap.pop();
     45         return heap.top();
     46     }
     47     int sdTOP()
     48     {
     49         int ls=TOP();POP();
     50         int ret=TOP();ins(ls);
     51         return ret;
     52     }
     53     int SIZE()
     54     {
     55         return heap.size()-delmark.size();
     56     }
     57 }s1[maxn],s2[maxn],ans;
     58 
     59 void addedge(int u,int v)
     60 {
     61     cnt++;e[cnt].u=u;e[cnt].v=v;
     62     e[cnt].next=head[u];head[u]=cnt;
     63 }
     64 void getroot(int x,int pa)
     65 {
     66     son[x]=1;f[x]=0;
     67     for (int i=head[x];i;i=e[i].next)
     68     {
     69         int y=e[i].v;
     70         if (can[y]||y==pa) continue;
     71         getroot(y,x);
     72         son[x]+=son[y];
     73         if (son[y]>f[x]) f[x]=son[y];
     74     }
     75     if (all-son[x]>f[x]) f[x]=all-son[x];
     76     if (f[x]<f[rt]) rt=x;
     77 }
     78 void dfs(int x,int pa,int dep,node &s)
     79 {
     80     s.ins(dep);
     81     for (int i=head[x];i;i=e[i].next)
     82     {
     83         int y=e[i].v;
     84         if (can[y]||y==pa) continue;
     85         dfs(y,x,dep+1,s);
     86     }
     87 }
     88 void insert(node &s)
     89 {
     90     if (s.SIZE()>=2)
     91     {
     92         int tmp=s.TOP()+s.sdTOP();
     93         ans.ins(tmp);
     94     }
     95 }
     96 void erase(node &s)
     97 {
     98     if (s.SIZE()>=2)
     99     {
    100         int tmp=s.TOP()+s.sdTOP();
    101         ans.del(tmp);
    102     }
    103 }
    104 void work(int x)
    105 {
    106     can[x]=1;
    107     s2[x].ins(0);
    108     for (int i=head[x];i;i=e[i].next)
    109     {
    110         int y=e[i].v;
    111         if (can[y]) continue;
    112         node s;
    113         dfs(y,x,1,s);
    114         all=son[y];f[rt=0]=n+1;
    115         getroot(y,0);
    116         int ls=rt;work(rt);
    117         fa[ls]=x;s1[ls]=s;
    118         s2[x].ins(s.TOP());
    119     }
    120     insert(s2[x]);
    121 }
    122 void getdep(int x,int pa)
    123 {
    124     a[pos[x]=++T][0]=dep[x]=dep[pa]+1;
    125     for (int i=head[x];i;i=e[i].next)
    126     {
    127         int y=e[i].v;
    128         if (y==pa) continue;
    129         getdep(y,x);
    130         a[++T][0]=dep[x];
    131     }
    132 }
    133 int lcadep(int x,int y)
    134 {
    135     x=pos[x],y=pos[y];
    136     if (x>y) swap(x,y);
    137     int ls=lg2[y-x+1];
    138     return min(a[x][ls],a[y-(1<<ls)+1][ls]);
    139 }
    140 int dis(int x,int y)
    141 {
    142     return dep[x]+dep[y]-2*lcadep(x,y);
    143 }
    144 void turnoff(int x)
    145 {
    146     erase(s2[x]);
    147     s2[x].ins(0);
    148     insert(s2[x]);
    149     for (int i=x;fa[i];i=fa[i])
    150     {
    151         erase(s2[fa[i]]);
    152         if (s1[i].SIZE())
    153         s2[fa[i]].del(s1[i].TOP());
    154         s1[i].ins(dis(fa[i],x));
    155         if (s1[i].SIZE())
    156         s2[fa[i]].ins(s1[i].TOP());
    157         insert(s2[fa[i]]);
    158     }
    159 }
    160 void turnon(int x)//del
    161 {
    162     erase(s2[x]);
    163     s2[x].del(0);
    164     insert(s2[x]);
    165     for (int i=x;fa[i];i=fa[i])
    166     {
    167         erase(s2[fa[i]]);
    168         if (s1[i].SIZE())
    169         s2[fa[i]].del(s1[i].TOP());
    170         s1[i].del(dis(fa[i],x));
    171         if (s1[i].SIZE())
    172         s2[fa[i]].ins(s1[i].TOP());
    173         insert(s2[fa[i]]);
    174     }
    175 }
    176 
    177 int main()
    178 {
    179     freopen("hide.in","r",stdin);
    180     freopen("hide.out","w",stdout);
    181     n=read();
    182     for (int i=1;i<n;i++) 
    183     {
    184         int u=read(),v=read();
    185         addedge(u,v);
    186         addedge(v,u);
    187     }
    188     f[rt=0]=n+1;all=n;
    189     getroot(1,0);work(rt);getdep(1,0);
    190     for (int i=2;i<=T;i++)
    191     lg2[i]=lg2[i>>1]+1;
    192     for (int j=1;j<=lg2[T];j++)
    193     for (int i=1;i+(1<<j)-1<=T;i++)
    194     a[i][j]=min(a[i][j-1],a[i+(1<<j-1)][j-1]);
    195     //0是关灯,1是开灯
    196     m=read();tot=n;
    197     char op[10];
    198     for (int i=1;i<=m;i++)
    199     {
    200         scanf("%s",op);
    201         if (op[0]=='C')
    202         {
    203             int ch=read();
    204             if (cdt[ch])
    205             {
    206                 tot++;cdt[ch]=0;
    207                 turnoff(ch);
    208             }
    209             else
    210             {
    211                 tot--;cdt[ch]=1;
    212                 turnon(ch);
    213             }
    214         }
    215         else
    216         {
    217             if (tot<=1) printf("%d
    ",tot-1);
    218             else printf("%d
    ",ans.TOP());
    219         }
    220     }
    221     fclose(stdin);
    222     fclose(stdout);
    223     return 0;
    224 }

    就酱w总算是搞完这题了天哪噜。

     
  • 相关阅读:
    百战天虫中子弹的挖坑效果
    as3对象销毁是否需要全部属性置null?
    事件冒泡其实就是它给它的parent send一个事件
    25个Photoshop创作的励志展示
    15个免费的关于杂志的wordpress主题
    wordpress主题:New Horizon 博客/创意展示主题[v1.0.3][荐](类似瀑布流)
    linux nl命令与逻辑页
    PLSQL用DBMS_JOB建立作业
    PLSQL DBMS_DDL.ANALYZE_OBJECT
    PLSQL的UTL_FILE使用例子
  • 原文地址:https://www.cnblogs.com/zengziyun/p/6895722.html
Copyright © 2011-2022 走看看