• 【离线 撤销并查集 线段树分治】bzoj1018: [SHOI2008]堵塞的交通traffic


    本题可化成更一般的问题:离线动态图询问连通性

    当然可以利用它的特殊性质,采用在线线段树维护一些标记的方法

    Description

      有一天,由于某种穿越现象作用,你来到了传说中的小人国。小人国的布局非常奇特,整个国家的交通系统可
    以被看成是一个2行C列的矩形网格,网格上的每个点代表一个城市,相邻的城市之间有一条道路,所以总共有2C个
    城市和3C-2条道路。 小人国的交通状况非常槽糕。有的时候由于交通堵塞,两座城市之间的道路会变得不连通,
    直到拥堵解决,道路才会恢复畅通。初来咋到的你决心毛遂自荐到交通部某份差事,部长听说你来自一个科技高度
    发达的世界,喜出望外地要求你编写一个查询应答系统,以挽救已经病入膏肓的小人国交通系统。 小人国的交通
    部将提供一些交通信息给你,你的任务是根据当前的交通情况回答查询的问题。交通信息可以分为以下几种格式:
    Close r1 c1 r2 c2:相邻的两座城市(r1,c1)和(r2,c2)之间的道路被堵塞了;Open r1 c1 r2 c2:相邻的两座城
    市(r1,c1)和(r2,c2)之间的道路被疏通了;Ask r1 c1 r2 c2:询问城市(r1,c1)和(r2,c2)是否连通。如果存在一
    条路径使得这两条城市连通,则返回Y,否则返回N;

    Input

      第一行只有一个整数C,表示网格的列数。接下来若干行,每行为一条交通信息,以单独的一行“Exit”作为
    结束。我们假设在一开始所有的道路都是堵塞的。我们保证 C小于等于100000,信息条数小于等于100000。

    Output

      对于每个查询,输出一个“Y”或“N”。


    题目分析

    这里提供一种更加一般的模型,即离线动态图连通性。

    大体的思路是:把所有操作都离线之后,对询问分治,将每个询问看做线段树的一个节点(因为询问天然有序),并且记录当前剩余操作(可以是在过程里带vector)。那么这样在处理到每个叶子节点的时候,就已经把有关的操作都执行了。最后离开当前节点时,按栈序撤销并查集操作。

    这个方法的时间复杂度是$O(m log m log n)$($log n$是可撤销并查集的复杂度)。其优化的本质在于,让一段共用边的操作同时处理。

    那么这里有一个很具有启发性的思路:对于一类询问$m$次,每次询问基于若干个元素的问题,可以通过离线分治的方式减少它们的冗余操作,将复杂度将为$O(m log m log n)$。当然最大的缺陷在于必须离线(而且过程里挂vector是不是太占空间了?)

     1 #include<bits/stdc++.h>
     2 const int maxn = 200035;
     3 
     4 struct Edge
     5 {
     6     int u,v,s,t;
     7     Edge(int a=0, int b=0, int c=0, int d=0):u(a),v(b),s(c),t(d) {}
     8 };
     9 int n,qNum,top;
    10 int mp[3][maxn],fat[maxn],size[maxn];
    11 typedef std::vector<Edge> vec;
    12 vec opt;
    13 std::map<int, int> tag[maxn];
    14 std::pair<int, int> qr[maxn],stk[maxn<<2];
    15 char str[5];
    16 
    17 int read()
    18 {
    19     char ch = getchar();
    20     int num = 0, fl = 1;
    21     for (; !isdigit(ch); ch=getchar())
    22         if (ch=='-') fl = -1;
    23     for (; isdigit(ch); ch=getchar())
    24         num = (num<<1)+(num<<3)+ch-48;
    25     return num*fl;
    26 }
    27 int find(int x)
    28 {
    29     while (x!=fat[x]) x = fat[x];
    30     return x;
    31 }
    32 void merge(int x, int y)
    33 {
    34     int fx = find(x), fy = find(y);
    35     if (size[fx] > size[fy]) std::swap(fx, fy);
    36     stk[++top] = std::make_pair(fx, fy);
    37     fat[fx] = fy, size[fy] += size[fx];
    38 }
    39 void cancel()
    40 {
    41     int x = stk[top].first, y = stk[top].second;
    42     fat[x] = x, size[y] -= size[x];
    43 }
    44 void solve(int l, int r, vec opt)
    45 {
    46     vec L,R;
    47     int mid = (l+r)>>1, tmp = top;
    48     for (int i=0, mx=opt.size(); i<mx; i++)
    49     {
    50         int s = opt[i].s, t = opt[i].t;
    51         if (s <= l&&r <= t) merge(opt[i].u, opt[i].v);
    52         else{
    53             if (s <= mid) L.push_back(opt[i]);
    54             if (t > mid) R.push_back(opt[i]);
    55         }
    56     }
    57     if (l==r) puts(find(qr[l].first)==find(qr[l].second)?"Y":"N");
    58     else solve(l, mid, L), solve(mid+1, r, R);
    59     while (tmp!=top) cancel(), --top;
    60 }
    61 int main()
    62 {
    63     n = read();
    64     for (int i=1, cnt=0; i<=n; i++)
    65         mp[1][i] = ++cnt, mp[2][i] = ++cnt;
    66     for (int idx,idy; ;)
    67     {
    68         scanf("%s",str);
    69         if (str[0]=='E') break;
    70         idx = mp[read()][read()], idy = mp[read()][read()];
    71         if (str[0]=='O'){
    72             opt.push_back(Edge(idx, idy, qNum+1, -1));
    73             tag[idx][idy] = tag[idy][idx] = opt.size()-1;
    74         }
    75         if (str[0]=='C') opt[tag[idx][idy]].t = qNum;
    76         if (str[0]=='A') qr[++qNum] = std::make_pair(idx, idy);
    77     }
    78     for (int i=0, mx=opt.size(); i<mx; i++)
    79         if (opt[i].t==-1) opt[i].t = qNum;
    80     for (int i=1; i<=(n<<1); i++) fat[i] = i, size[i] = 1;
    81     solve(1, qNum, opt);
    82     return 0;
    83 }

    END

  • 相关阅读:
    什么是ORM
    ORM优缺点
    Azure 中快速搭建 FTPS 服务
    连接到 Azure 上的 SQL Server 虚拟机(经典部署)
    在 Azure 虚拟机中配置 Always On 可用性组(经典)
    SQL Server 2014 虚拟机的自动备份 (Resource Manager)
    Azure 虚拟机上的 SQL Server 常见问题
    排查在 Azure 中新建 Windows 虚拟机时遇到的经典部署问题
    上传通用化 VHD 并使用它在 Azure 中创建新 VM
    排查在 Azure 中新建 Windows VM 时遇到的部署问题
  • 原文地址:https://www.cnblogs.com/antiquality/p/10253684.html
Copyright © 2020-2023  润新知