zoukankan      html  css  js  c++  java
  • 洛谷P3300 城市规划

    题意:给你一个6 * n的网格题,单点修改,询问区间联通块数。n <= 10w

    解:看起来就很显然的一道题......线段树每个点用一个ufs维护连通性。完了。

    我为了方便思考把图转成横着的了。

    写起来真是毒瘤......

    重点在于:1.建立叶节点。2.合并两个子节点。3.把新的并查集的中间两列压掉。

    第一步,这个就直接枚举,merge就完事了。

    第二步,把两个2列的子并查集copy到当前节点的4列的并查集上。注意右边那个并查集,fa全部要加2m,因为下标加了2m。

    然后枚举中间两列merge。这样也做完了。

    第三步,我们只要保留两边的两列即可。注意到有可能有两边元素的代表元在中间,我们使用左偏树技巧,切换代表元到它自己,注意vis也要变。

    然后把两边的vis和facopy一份出来,用以查询代表元。

    然后把前两列init,然后枚举每个元素,跟它的代表元merge。注意这一步会对连通块总数tot造成改变,最后复原即可。

    最后把前两列的vis和lk从copy的那里拿来用即可。

    注意,vis(当前联通块是否有建筑物)要继承代表元的,lk(能否与两边连通)直接从对应下标继承,这两个不一样!

    具体实现看代码吧......

      1 #include <bits/stdc++.h>
      2 
      3 #define ck(x) ((x) == '+' || (x) == '|')
      4 
      5 const int N = 100010;
      6 
      7 template <typename T> inline void read(T &x) {
      8     x = 0;
      9     char c = getchar();
     10     while(c < '0' || c > '9') {
     11         c = getchar();
     12     }
     13     while(c >= '0' && c <= '9') {
     14         x = x * 10 + c - 48;
     15         c = getchar();
     16     }
     17     return;
     18 }
     19 
     20 int n, m, gt[24], GT, exfa[24], exvis[24], exlk[24], newvis[24], newlk[24];
     21 
     22 int exfind(int x) {
     23     return (x == exfa[x]) ? x : exfa[x] = exfind(exfa[x]);
     24 }
     25 
     26 inline int trans(int x) {
     27     return x < m ? x : x - (m << 1);
     28 }
     29 
     30 struct Node {
     31     int fa[24], tot;
     32     std::bitset<24> lk, vis;
     33     int find(int x) {
     34         return (x == fa[x]) ? x : (fa[x] = find(fa[x]));
     35     }
     36     inline void Merge(int x, int y) {
     37         x = find(x);
     38         y = find(y);
     39         if(x == y) return;
     40         fa[y] = x;
     41         tot -= (vis[x] && vis[y]);
     42         if(vis[y]) vis.set(x);
     43         return;
     44     }
     45     Node() {}
     46     Node(char *a) {
     47         tot = 0;
     48         for(register int i(0); i < m; ++i) {
     49             fa[i + m] = fa[i] = i;
     50             if(a[i] == 'O') {
     51                 vis.set(i);
     52                 vis.set(i + m);
     53                 lk.set(i);
     54                 lk.set(i + m);
     55                 ++tot;
     56             }
     57             else if(a[i] == '.') {
     58                 vis.reset(i);
     59                 vis.reset(i + m);
     60                 lk.reset(i);
     61                 lk.reset(i + m);
     62             }
     63             else if(a[i] == '-' || a[i] == '+') {
     64                 vis.reset(i);
     65                 vis.reset(i + m);
     66                 lk.set(i);
     67                 lk.set(i + m);
     68             }
     69         }
     70         for(register int i(1); i < m; ++i) {
     71             if(ck(a[i - 1]) && ck(a[i])) {
     72                 Merge(i - 1, i);
     73             }
     74             else if((ck(a[i - 1]) && a[i] == 'O') || (ck(a[i]) && a[i - 1] == 'O')) {
     75                 Merge(i - 1, i);
     76             }
     77             else if(a[i] == 'O' && a[i - 1] == 'O') {
     78                 Merge(i - 1, i);
     79             }
     80         }
     81     }
     82     inline void update() {
     83         for(register int i(0); i < m; ++i) {
     84             int t(find(i));
     85             fa[i] = fa[t] = i;
     86             vis[i] = vis[t];
     87 
     88             t = find(i + m * 3);
     89             fa[i + m * 3] = fa[t] = i + m * 3;
     90             vis[i + m * 3] = vis[t];
     91         }
     92 
     93         memcpy(exfa, fa, sizeof(fa));
     94         for(register int i(0); i < m; ++i) {
     95             exvis[i] = vis[i];
     96             exvis[i + m * 3] = vis[i + m * 3];
     97             exlk[i] = lk[i];
     98             exlk[i + m * 3] = lk[i + m * 3];
     99         }
    100 
    101         int temp = tot;
    102         for(register int i(0); i < m; ++i) {
    103             fa[i] = i;
    104             fa[i + m] = i + m;
    105         }
    106         for(register int i(0); i < m; ++i) {
    107             Merge(i, trans(exfind(i)));
    108             Merge(i + m, trans(exfind(i + m * 3)));
    109         }
    110         for(register int i(0); i < m; ++i) {
    111             vis[i] = exvis[exfind(i)];
    112             vis[i + m] = exvis[exfind(i + m * 3)];
    113             lk[i] = exlk[i];
    114             lk[i + m] = exlk[i + m * 3];
    115         }
    116         tot = temp;
    117         return;
    118     }
    119     inline Node merge(const Node &w) const {
    120         Node ans;
    121         /// copy
    122         for(register int i(0); i < m; ++i) {
    123             ans.fa[i] = fa[i];
    124             ans.lk[i] = lk[i];
    125             ans.vis[i] = vis[i];
    126 
    127             ans.fa[i + m] = fa[i + m];
    128             ans.lk[i + m] = lk[i + m];
    129             ans.vis[i + m] = vis[i + m];
    130 
    131             ans.fa[i + m * 2] = w.fa[i] + m * 2;
    132             ans.lk[i + m * 2] = w.lk[i];
    133             ans.vis[i + m * 2] = w.vis[i];
    134 
    135             ans.fa[i + m * 3] = w.fa[i + m] + m * 2;
    136             ans.lk[i + m * 3] = w.lk[i + m];
    137             ans.vis[i + m * 3] = w.vis[i + m];
    138         }
    139         ans.tot = tot + w.tot;
    140         /// merge
    141         for(register int i(0); i < m; ++i) {
    142             if(ans.lk[i + m] && ans.lk[i + m * 2]) { /// -> <-
    143                 ans.Merge(i + m, i + m * 2);
    144             }
    145         }
    146         ans.update();
    147         return ans;
    148     }
    149 }node[N << 2];
    150 
    151 char str[N][6];
    152 
    153 void build(int l, int r, int o) {
    154     if(l == r) {
    155         node[o] = Node(str[r]);
    156         return;
    157     }
    158     int mid = (l + r) >> 1;
    159     build(l, mid, o << 1);
    160     build(mid + 1, r, o << 1 | 1);
    161     node[o] = node[o << 1].merge(node[o << 1 | 1]);
    162     return;
    163 }
    164 
    165 void change(int p, int l, int r, int o) {
    166     if(l == r) {
    167         node[o] = Node(str[r]);
    168         return;
    169     }
    170     int mid = (l + r) >> 1;
    171     if(p <= mid) {
    172         change(p, l, mid, o << 1);
    173     }
    174     else {
    175         change(p, mid + 1, r, o << 1 | 1);
    176     }
    177     node[o] = node[o << 1].merge(node[o << 1 | 1]);
    178     return;
    179 }
    180 
    181 Node ask(int L, int R, int l, int r, int o) {
    182     if(L <= l && r <= R) {
    183         return node[o];
    184     }
    185     int mid = (l + r) >> 1;
    186     if(R <= mid) {
    187         return ask(L, R, l, mid, o << 1);
    188     }
    189     if(mid < L) {
    190         return ask(L, R, mid + 1, r, o << 1 | 1);
    191     }
    192     Node temp(ask(L, R, l, mid, o << 1));
    193     temp = temp.merge(ask(L, R, mid + 1, r, o << 1 | 1));
    194     return temp;
    195 }
    196 
    197 int main() {
    198 
    199     read(n); read(m);
    200     for(int i = 1; i <= n; i++) {
    201         scanf("%s", str[i]);
    202         for(int j = 0; j < m; j++) {
    203             if(str[i][j] == '-') {
    204                 str[i][j] = '|';
    205             }
    206             else if(str[i][j] == '|') {
    207                 str[i][j] = '-';
    208             }
    209         }
    210     }
    211 
    212     build(1, n, 1);
    213 
    214     int q, x, y;
    215     char ss[2];
    216     read(q);
    217     for(int i = 1; i <= q; i++) {
    218         scanf("%s", ss); read(x); read(y);
    219         if(ss[0] == 'C') { /// change
    220             scanf("%s", ss);
    221             if(ss[0] == '-') {
    222                 ss[0] = '|';
    223             }
    224             else if(ss[0] == '|') {
    225                 ss[0] = '-';
    226             }
    227             str[x][y - 1] = ss[0];
    228             change(x, 1, n, 1);
    229         }
    230         else { /// Query
    231             Node temp = ask(x, y, 1, n, 1);
    232             printf("%d
    ", temp.tot);
    233         }
    234     }
    235 
    236     return 0;
    237 }
    AC代码

    这代码常数奇大...

  • 相关阅读:
    c# 4.0新功能--隐式类型
    常用的sql语句记录
    算法学习-回文数判断
    算法学习-两数之和
    RSA加密(前端js)和MD5加密(后台)同时使用实例
    layer父页获取弹出层输入框里面的值
    关于checkbox的全选和反选实例
    jQuery实用小技巧-获取选中的的下拉框和返回头部滑动动画
    jQuery实用小技巧--输入框文字获取和失去焦点
    得到网站下的文件虚拟路径的方法
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10841280.html
Copyright © 2011-2022 走看看