zoukankan      html  css  js  c++  java
  • Bzoj1095 [ZJOI2007]Hide 捉迷藏

    Time Limit: 40 Sec  Memory Limit: 256 MB
    Submit: 3369  Solved: 1383

    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。

    Source

    动态点分治

    看到还有种线段树做法跑得飞快,姑且mark下,日后研究

    先根据原树建出点分治树,保证树深度小于logn

    在点分治树上处理问题,维护三种堆:1、每个结点的子树中,该结点到子节点的距离;2、每个结点的子结点的1种堆堆顶;3、每个结点的2种堆的最大值和次大值之和

    记录每层祖先,改变某结点存在性时,暴力上溯最多logn次即可。

    3号堆的堆顶就是答案。

    STL大法好,priority_queue可以省不少力

    ↑然而即使“省了不少力“,还是花了一上午才调对。

      ↑原因是试图一边建树一边更新信息,然后代码太乱了,人又困,傻傻找不出错。最后干脆重构代码,老实建完树再一个个更新结点信息,又调了一阵子终于A了

      1 /*by SilverN*/
      2 #include<algorithm>
      3 #include<iostream>
      4 #include<cstring>
      5 #include<cstdio>
      6 #include<cmath>
      7 #include<vector>
      8 #include<queue>
      9 using namespace std;
     10 const int mxn=100010;
     11 int read(){
     12     int x=0,f=1;char ch=getchar();
     13     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     14     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
     15     return x*f;
     16 }
     17 struct edge{int v,nxt;}e[mxn<<1];
     18 int hd[mxn],mct=0;
     19 void add_edge(int u,int v){
     20     e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct;return;
     21 }
     22 int n,m;
     23 int light[mxn];
     24 struct Heap{
     25     priority_queue<int>hp,dl;
     26     void push(int x){hp.push(x);}
     27     void del(int x){dl.push(x);}
     28     int size(){return hp.size()-dl.size();}
     29     void pop(){
     30         while(!dl.empty() && dl.top()==hp.top()){dl.pop();hp.pop();}
     31         hp.pop();
     32     }
     33     int top(){
     34         while(!dl.empty() && dl.top()==hp.top()){dl.pop();hp.pop();}
     35         return hp.top();
     36     }
     37     int second(){
     38         int x=top();pop();    int y=top();push(x);
     39         return y;
     40     }
     41 }s1[mxn],s2[mxn],s;
     42 void insert(Heap &p){
     43     if(p.size()>=2){
     44         int tmp=p.top()+p.second();
     45         s.push(tmp);
     46     }
     47     return;
     48 }
     49 void Erase(Heap &p){
     50     if(p.size()>=2){
     51         int tmp=p.top()+p.second();
     52         s.del(tmp);
     53     }
     54     return;
     55 }
     56 int sz[mxn],mc[mxn],rt,smm;
     57 bool vis[mxn];
     58 void DFS_sz(int u,int fa){
     59     sz[u]=1;mc[u]=0;
     60     for(int i=hd[u];i;i=e[i].nxt){
     61         int v=e[i].v;if(vis[v] || v==fa)continue;
     62         DFS_sz(v,u);
     63         sz[u]+=sz[v];
     64         mc[u]=max(mc[u],sz[v]);
     65     }
     66     mc[u]=max(mc[u],smm-mc[u]);
     67     if(mc[u]<mc[rt])rt=u;
     68     return;
     69 }
     70 int f[mxn][20],dis[mxn][20];
     71 int dep[mxn];
     72 void getship(int u,int fa,int an,int d){
     73 //    printf("GS:u:%d fa:%d an:%d d:%d
    ",u,fa,an,d);
     74     for(int i=hd[u];i;i=e[i].nxt){
     75         int v=e[i].v;if(vis[v] || v==fa)continue;
     76         f[v][++dep[v]]=an;
     77         dis[v][dep[v]]=d;
     78         getship(v,u,an,d+1);
     79     }
     80     return;
     81 }
     82 void solve(int x,int ff){
     83 //    printf("Rt:%d
    ",x);
     84     vis[x]=1;
     85     getship(x,0,x,1);
     86     for(int i=hd[x];i;i=e[i].nxt){
     87         if(vis[e[i].v])continue;int v=e[i].v;
     88         rt=0;smm=sz[v];
     89         DFS_sz(v,0);
     90         solve(rt,x);
     91     }
     92     return;
     93 }
     94 void update(int x,int mode){
     95 //    printf("update:%d  mode:%d
    ",x,mode);
     96     Erase(s2[x]);
     97     if(!mode){s2[x].push(0);insert(s2[x]);}
     98     else{s2[x].del(0);insert(s2[x]);}
     99     for(int i=dep[x];i>1;i--){
    100 //        printf("anc%d : %d  dis:%d
    ",i,f[x][i],dis[x][i]);
    101         if(!mode){//关灯 
    102             Erase(s2[f[x][i-1]]);
    103             
    104             if(s1[f[x][i]].size()) s2[f[x][i-1]].del(s1[f[x][i]].top());
    105             s1[f[x][i]].push(dis[x][i-1]);
    106             if(s1[f[x][i]].size()) s2[f[x][i-1]].push(s1[f[x][i]].top());
    107             
    108             insert(s2[f[x][i-1]]);
    109         }
    110         else{//开灯 
    111             Erase(s2[f[x][i-1]]);
    112             
    113             if(s1[f[x][i]].size()) s2[f[x][i-1]].del(s1[f[x][i]].top());
    114             s1[f[x][i]].del(dis[x][i-1]);
    115             if(s1[f[x][i]].size()) s2[f[x][i-1]].push(s1[f[x][i]].top());
    116             
    117             insert(s2[f[x][i-1]]);
    118         }
    119     }
    120     return;
    121 }
    122 int lcnt=0;
    123 int Que(){if(lcnt>1 && s.size())return s.top();else return lcnt-1;}
    124 int main(){
    125     int i,j,u,v;
    126     n=read();
    127     for(i=1;i<n;i++){
    128         u=read();v=read();
    129         add_edge(u,v);
    130         add_edge(v,u);
    131     }
    132     smm=n;
    133     mc[rt=0]=1e8;
    134     DFS_sz(1,0);
    135     solve(rt,0);
    136     lcnt=n;
    137     for(i=1;i<=n;i++)f[i][++dep[i]]=i;
    138     for(i=1;i<=n;i++)update(i,0);
    139     m=read();
    140     char op[5];
    141     while(m--){
    142         scanf("%s",op);
    143         if(op[0]=='C'){
    144             u=read();
    145             light[u]^=1;
    146             if(light[u])lcnt--;
    147             else lcnt++;
    148             update(u,light[u]);
    149         }
    150         else{
    151 //            printf("G!!
    ");
    152             int ans=Que();
    153             printf("%d
    ",ans);
    154         }
    155     }
    156     return 0;
    157 }
  • 相关阅读:
    #pragma 预处理指令
    C++类继承中的构造函数和析构函数 调用顺序
    static_cast与dynamic_cast转换 最简单的理解
    std::map的insert和下标[]访问
    C++有没有string转化int的函数,怎样转换
    c++中在一个类中定义另一个只有带参数构造函数的类的对象
    c++二进制文件的读写
    C++ 包含头文件 和 宏的使用 和 条件编译
    C++ 前置声明 和 包含头文件 如何选择
    C语言 gets()和scanf()函数的区别
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6424404.html
Copyright © 2011-2022 走看看