zoukankan      html  css  js  c++  java
  • BZOJ5017 [SNOI2017]炸弹

    Solution

    一个点向一个区间内的所有点连边, 可以用线段树优化建图来优化 : 前置技能传送门

    然后就得到一个有向图, 一个联通块内的炸弹可以互相引爆, 所以进行缩点变成$DAG$

    然后拓扑排序。 由于一次引爆的炸弹 一定是一个连续的区间内, 所以只需要记录左右边界, 并将左右边界转移给能到达它的联通块。

    没写手工栈一直RE的我心里$mmp$啊。 为什么网上的题解都不写手工栈$QAQ$

    Code

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #define rd read()
      5 #define ll long long
      6 using namespace std;
      7   
      8 const int N = 2000010;
      9 const int mod = 1e9 + 7;
     10 const ll inf = 3e18;
     11   
     12 int n, lscnt;
     13 int head[N], tot;
     14 int Head[N], Tot;
     15 int low[N], dfn[N], dfstot;
     16 int c[N], col;
     17 ll minn[N], maxn[N], ls[N];
     18 int st[N], tp;
     19 bool vis[N], inq[N];
     20   
     21 struct edge {
     22     int nxt, to;
     23 }e[N * 10], E[N * 10];
     24   
     25 struct boom {
     26     ll pos, r;
     27 }bo[N];
     28   
     29 ll read() {
     30     ll X = 0, p = 1; char c = getchar();
     31     for (; c > '9' || c < '0'; c = getchar())
     32         if (c == '-') p = -1;
     33     for (; c >= '0' && c <= '9'; c = getchar())
     34         X = X * 10 + c - '0';
     35     return X * p;
     36 }
     37   
     38 void add(int u, int v) {
     39     e[++tot].to = v;
     40     e[tot].nxt = head[u];
     41     head[u] = tot;
     42 }
     43   
     44 void Add(int u, int v) {
     45     E[++Tot].to = v;
     46     E[Tot].nxt = Head[u];
     47     Head[u] = Tot;
     48 }
     49   
     50 namespace SegT {
     51 #define mid ((l + r) >> 1)
     52     int lc[N], rc[N], root, cnt;
     53   
     54     void build(int &p, int l, int r) {
     55         if (l == r) {
     56             p = l; return;
     57         }
     58         p = ++cnt;
     59         build(lc[p], l, mid);
     60         build(rc[p], mid + 1, r);
     61         add(p, lc[p]); add(p, rc[p]);
     62     }
     63   
     64     void update(int L, int R, int c, int l, int r, int x) {
     65         if (L > R) return;
     66         if (L <= l && r <= R) {
     67             add(c, x); return;
     68         }
     69         if (mid >= L)
     70             update(L, R, c, l,mid, lc[x]);
     71         if (mid < R)
     72             update(L, R, c, mid + 1, r, rc[x]);
     73     }
     74 }using namespace SegT;
     75   
     76 #define R register
     77 int stx[N], sti[N], lv, stnt[N];
     78 #define u stx[lv]
     79 #define nt stnt[lv]
     80 #define i sti[lv]
     81 void tarjan(int x) {
     82     lv = 1; stx[1] = x;
     83 start:;
     84     low[u] = dfn[u] = ++dfstot;
     85     inq[u] = true; st[++tp] = u;
     86     for (i = head[u]; i; i = e[i].nxt) {
     87         nt = e[i].to;
     88         if (!dfn[nt]) {
     89 //         tarjan(nt);
     90             stx[lv + 1] = nt;
     91             lv++;
     92             goto start;
     93             end:;
     94             low[u] = min(low[u], low[nt]);
     95         }
     96         else if (inq[nt]) low[u] = min(low[u], dfn[nt]);
     97     }
     98     if (low[u] == dfn[u]) {
     99         col++;
    100         for (; tp;) {
    101             int z = st[tp--];
    102             inq[z] = false;
    103             if (z <= n) 
    104                 maxn[col] = max(maxn[col], bo[z].pos + bo[z].r),
    105                 minn[col] = min(minn[col], bo[z].pos - bo[z].r);
    106             c[z] = col;
    107             if (z == u) break;
    108         }
    109     }
    110     --lv;
    111 if (lv) goto end;
    112 }
    113 #undef u
    114 #undef nt
    115 #undef i
    116   
    117 void dfs(int u) {
    118     vis[u] = true;
    119     for (R int i = Head[u]; i; i = E[i].nxt) {
    120         int nt = E[i].to;
    121         if (vis[nt] == false) dfs(nt);
    122         minn[u] = min(minn[u], minn[nt]);
    123         maxn[u] = max(maxn[u], maxn[nt]);
    124     }
    125 }
    126   
    127 int fdl(ll x) {
    128     return lower_bound(ls + 1, ls + 1 + lscnt, x) - ls;
    129 }
    130   
    131 int fdr(ll x) {
    132     int re = lower_bound(ls + 1, ls + 1 + lscnt, x) - ls;
    133     if (ls[re] == x) return re;
    134     else return re - 1;
    135 }
    136   
    137 int main()
    138 {
    139     cnt = n = rd;
    140     for (R int i = 1; i <= n; ++i) {
    141         bo[i].pos = rd; bo[i].r = rd;
    142         ls[++lscnt] = bo[i].pos;
    143     }
    144     sort(ls + 1, ls + 1 + lscnt);
    145     lscnt = unique(ls + 1, ls + 1 + lscnt) - ls - 1;
    146     build(root, 1, n);
    147     for (int i = 1; i <= n; ++i) {
    148         int l = fdl(bo[i].pos - bo[i].r), r = fdr(bo[i].pos + bo[i].r), m = fdl(bo[i].pos);
    149         update(l, m - 1, m, 1, n, root);
    150         update(m + 1, r, m, 1, n, root);
    151     }
    152     for (int i = 1; i < N; ++i)
    153         maxn[i] = -inf, minn[i] = inf;
    154     for (int i = 1; i <= cnt; ++i)
    155         if (!dfn[i]) tarjan(i);
    156     for (int u = 1; u <= cnt; ++u) 
    157         for (int i = head[u]; i; i = e[i].nxt) {
    158             int v = e[i].to;
    159             if (c[u] == c[v])
    160                 continue;
    161             Add(c[u], c[v]);
    162         }
    163     for (int i = 1; i <= col; ++i) dfs(i);
    164     ll ans = 0;
    165     for (int i = 1; i <= n; ++i) {
    166         int l = fdl(minn[c[i]]), r = fdr(maxn[c[i]]);
    167         (ans += 1LL * i * (r - l + 1) % mod) %= mod;
    168     }
    169     printf("%lld
    ", ans);
    170 }
    View Code
  • 相关阅读:
    从Oracle提供两种cube产品说开
    Sql Server DWBI的几个学习资料
    Unload Oracle data into text file
    初学Java的几个tips
    我常用的Oracle知识点汇总
    benefits by using svn
    如何在windows上使用putty来显示远端linux的桌面
    building commercial website using Microsoft tech stack
    Understand Thread and Lock
    Update google calendar by sunbird
  • 原文地址:https://www.cnblogs.com/cychester/p/9831720.html
Copyright © 2011-2022 走看看