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


    题目大意

    给定一棵树,每个点的颜色不是黑色就是白色,开始所有点的颜色都是黑色,要求支持两个操作:

    1. 翻转一个点的颜色
    2. 询问最远的黑点对的距离。如果只有1个黑点,那么输出0,如果没有黑点,输出-1。

      由于有多次询问,所以不可能暴力求最长链。

      如何快速处理最长链?于是想到了点分治。

      现在的任务是让点分治支持修改操作。

      因为最长距离不可加减,所以只能通过维护分治中心的各子树中,深度最大的点,然后取前两大更新答案。

      因此,每个点维护两个堆,一个堆维护点分树上它的子树中深度最大的点的深度,一个堆维护在点分树上它的子树中所有点到它的父分治中心的距离。

      除此之外,还要开一个全局堆维护答案。

      对于修改操作,就是删除元素再插入元素,自己画画图就能想清楚(明明是yyf扯不清楚)

      问题是怎么让堆支持删除?再开个堆打标记就好了。

      还有一个问题,如何求树上两点间的距离?两点的深度减去它们LCA的深度的两倍,求LCA用st表。

    Code

      1 /**
      2  * bzoj
      3  * Problem#1095
      4  * Accepted
      5  * Time: 13356ms
      6  * Memory: 159584k
      7  */ 
      8 #include <bits/stdc++.h>
      9 using namespace std;
     10 typedef bool boolean;
     11 const signed int inf = (signed) (~0u >> 1) - 1;
     12 
     13 typedef class Node {
     14     public:
     15         int val;
     16         Node *l, *r;
     17         
     18         Node(int val = 0, Node* l = NULL, Node* r = NULL):val(val), l(l), r(r) {        }
     19 }Node;
     20 
     21 Node* merge(Node* a, Node* b) {
     22     if(!a)    return b;
     23     if(!b)    return a;
     24     if(a->val < b->val)    swap(a, b);
     25     a->r = merge(a->r, b);
     26     swap(a->l, a->r);
     27     return a;
     28 }
     29 
     30 #define Limit 10000000
     31 Node pool[Limit];
     32 Node *top = pool;
     33 
     34 Node* newnode(int x) {
     35     if(top >= pool + Limit)
     36         return new Node(x, NULL, NULL);
     37     top->val = x;
     38     return top++;
     39 }
     40 
     41 #define clr(rt, dr) while(rt && dr && dr->val == rt->val)    rt = merge(rt->l, rt->r), dr = merge(dr->l, dr->r)
     42 typedef class Heap {
     43     public:
     44         int s;
     45         Node* rt;
     46         Node* dr;
     47         
     48         Heap():s(0), rt(NULL), dr(NULL) {        }
     49         
     50         int top() {
     51             if(!rt)    return -1;
     52             return rt->val;
     53         }
     54         
     55         int sectop() {
     56             if(!rt)    return -inf;
     57             clr(rt->l, dr);
     58             clr(rt->r, dr);
     59             int lv = (rt->l) ? (rt->l->val) : (-inf), rv = (rt->r) ? (rt->r->val) : (-inf);
     60             return (lv > rv) ? (lv) : (rv);
     61         }
     62         
     63         void pop() {
     64             rt = merge(rt->l, rt->r);
     65             clr(rt, dr);
     66         }
     67         
     68         void insert(int x) {
     69             if(x < 0)    return;
     70             s++;
     71             rt = merge(rt, newnode(x));
     72             clr(rt, dr);
     73         }
     74         
     75         void remove(int x) {
     76             if(x < 0)    return;
     77             s--;
     78             dr = merge(dr, newnode(x));
     79             clr(rt, dr);
     80         }
     81         
     82         int size() {
     83             return s;
     84         }
     85 }Heap;
     86 
     87 const int N = 1e5 + 5;
     88 
     89 int n, m, n2;
     90 vector<int> *g;
     91 Heap *dtg, *dtf, gol; 
     92 int *siz, *fag, *dep, *erl;
     93 int *Log2, *in;
     94 boolean *vis, *ison;
     95 
     96 inline void init() {
     97     scanf("%d", &n), n2 = n << 1;
     98     g = new vector<int>[(n + 1)];
     99     dtg = new Heap[(n + 1)];
    100     dtf = new Heap[(n + 1)];
    101     in = new int[(n + 1)];
    102     siz = new int[(n + 1)];
    103     fag = new int[(n + 1)];
    104     dep = new int[(n + 1)];
    105     erl = new int[(n2 + 1)];
    106     Log2 = new int[(n2 + 1)];
    107     vis = new boolean[(n + 1)];
    108     ison = new boolean[(n + 1)];
    109     fill(vis + 1, vis + n + 1, false);
    110     fill(ison + 1, ison + n + 1, false);
    111     for(int i = 1, u, v; i < n; i++) {
    112         scanf("%d%d", &u, &v);
    113         g[u].push_back(v);
    114         g[v].push_back(u);
    115     }
    116 }
    117 
    118 int cerl = 0;
    119 void dfs1(int p, int fa) {
    120     erl[++cerl] = p;
    121     in[p] = cerl;
    122     dep[p] = dep[fa] + 1;
    123     for(int i = 0; i < (signed)g[p].size(); i++) {
    124         int e = g[p][i];
    125         if(e == fa)    continue;
    126         dfs1(e, p);
    127         erl[++cerl] = p;
    128     }
    129 }
    130 
    131 #define bzmax 19
    132 int st[19][N << 1];
    133 inline void init_st() {
    134     Log2[1] = 0, dep[0] = 0;
    135     for(int i = 2; i <= n2; i++)
    136         Log2[i] = Log2[i >> 1] + 1;
    137     dfs1(1, 0);
    138     
    139     for(int i = 1; i < n2 - 1; i++)
    140         st[0][i] = (dep[erl[i]] < dep[erl[i + 1]]) ? (erl[i]) : (erl[i + 1]);
    141     for(int j = 1; j < bzmax; j++)
    142         for(int i = 1, a, b; i + (1 << j) < n2; i++) {
    143             a = st[j - 1][i], b = st[j - 1][i + (1 << (j - 1))];
    144             st[j][i] = (dep[a] < dep[b]) ? (a) : (b);
    145         }
    146 }
    147 
    148 inline int Lca(int u, int v) {
    149     int l = in[u], r = in[v], len, a, b;
    150     if(l > r)    swap(l, r);
    151     len = Log2[r - l + 1];
    152     a = st[len][l], b = st[len][r - (1 << len) + 1];
    153     return (dep[a] < dep[b]) ? (a) : (b);
    154 }
    155 
    156 inline int dist(int u, int v) {
    157     int lca = Lca(u, v);
    158     return dep[u] + dep[v] - (dep[lca] << 1);
    159 }
    160 
    161 void dfs2(int p, int fa) {
    162     siz[p] = 1;
    163     for(int i = 0; i < (signed)g[p].size(); i++) {
    164         int e = g[p][i];
    165         if(e == fa || vis[e])    continue;
    166         dfs2(e, p);
    167         siz[p] += siz[e];
    168     }
    169 }
    170 
    171 void dfs3(int p, int fa, int& cov, int& G, int& maxv) {
    172     int cmp = cov - siz[p];
    173     for(int i = 0; i < (signed)g[p].size(); i++) {
    174         int e = g[p][i];
    175         if(e == fa || vis[e])    continue;
    176         dfs3(e, p, cov, G, maxv);
    177         cmp = (siz[e] > cmp) ? (siz[e]) : (cmp);
    178     }
    179     if(cmp < maxv)
    180         maxv = cmp, G = p;
    181 }
    182 
    183 void dfs4(int p, int fa, int dep, int G, int fG) {
    184     if(fG)    dtf[G].insert(dist(p, fG));
    185     for(int i = 0; i < (signed)g[p].size(); i++) {
    186         int e = g[p][i];
    187         if(e == fa || vis[e])    continue;
    188         dfs4(e, p, dep + 1, G, fG);
    189     }
    190 }
    191 
    192 #define get_val(h)    (h.size() <= 1) ? ((h.size() == 1) ? (0) : (-1)) : (h.top() + h.sectop())
    193 int dividing(int p, int fag) {
    194     dfs2(p, 0);
    195     int G, maxv = inf, sG;
    196     dfs3(p, 0, siz[p], G, maxv);
    197     vis[G] = true, ::fag[G] = fag;
    198     dfs4(G, 0, 0, G, fag);
    199     dtg[G].insert(0);
    200     for(int i = 0; i < (signed)g[G].size(); i++) {
    201         int e = g[G][i];
    202         if(vis[e])    continue;
    203         sG = dividing(e, G);
    204         dtg[G].insert(dtf[sG].top());
    205     }
    206     gol.insert(get_val(dtg[G]));
    207     return G;
    208 }
    209 
    210 void turn_on(int p) {
    211     int G = p, oldt = 0, newt = -1;
    212     ison[p] = true;
    213     while (G) {
    214         if(oldt != newt) {
    215             gol.remove(get_val(dtg[G]));
    216             dtg[G].remove(oldt);
    217             if(~newt)    dtg[G].insert(newt);
    218             gol.insert(get_val(dtg[G]));
    219         }
    220         if (fag[G]) {
    221             oldt = dtf[G].top();
    222             dtf[G].remove(dist(p, fag[G]));
    223             newt = dtf[G].top();
    224         }
    225         G = fag[G];
    226     }
    227 }
    228 
    229 void turn_off(int p) {
    230     int G = p, oldt = -1, newt = 0;
    231     ison[p] = false;
    232     while (G) {
    233         if(oldt != newt) {
    234             gol.remove(get_val(dtg[G]));
    235             if(~oldt)    dtg[G].remove(oldt);
    236             dtg[G].insert(newt);
    237             gol.insert(get_val(dtg[G]));
    238         }
    239         if(fag[G]) {
    240             oldt = dtf[G].top();
    241             dtf[G].insert(dist(p, fag[G]));
    242             newt = dtf[G].top();
    243         }
    244         G = fag[G];
    245     }
    246 }
    247 
    248 inline void solve() {
    249     scanf("%d", &m);
    250     char buf[10];
    251     int x;
    252     while (m--) {
    253         scanf("%s", buf);
    254         if(buf[0] == 'G') {
    255             int x = gol.top();
    256             printf("%d
    ", x);
    257         } else {
    258             scanf("%d", &x);
    259             if(ison[x])
    260                 turn_off(x);
    261             else
    262                 turn_on(x);
    263         }
    264     }
    265 }
    266 
    267 int main() {
    268     init();
    269     init_st();
    270     dividing(1, 0);
    271     solve();
    272     return 0;
    273 }
  • 相关阅读:
    lua与C++的绑定
    lua与C的绑定
    如何得到真实的需求?
    mysql学习笔记——对数据库的操作
    排列组合公式
    英语口语积累笔记
    初学C++-----------------类的组合
    初学C++-----------------类的拷贝构造函数
    初学C++-----------------类的构造函数、析构函数
    初学C++-----------------类的定义
  • 原文地址:https://www.cnblogs.com/yyf0309/p/8283214.html
Copyright © 2011-2022 走看看