飘扬的旗帜

我也不知道哪里蒯来的题。反正二分 + 2-sat + 线段树优化连边就完事了。

注意答案可能为0..

  1 #include <bits/stdc++.h>
  2 
  3 const int N = 100010;
  4 
  5 struct Edge {
  6     int nex, v;
  7 }edge[3000010]; int tp;
  8 
  9 struct Node {
 10     int x, f;
 11     Node(int X = 0, int F = 0) {
 12         x = X;
 13         f = F;
 14     }
 15 };
 16 
 17 int e[N], num, dfn[N], low[N], X[N], xx, tot, n, fr[N], scc_cnt, ls[N], rs[N];
 18 std::vector<Node> v[N];
 19 int stk[N], top, rt, A[N],  B[N];
 20 
 21 inline void add(int x, int y) {
 22     tp++;
 23     edge[tp].v = y;
 24     edge[tp].nex = e[x];
 25     e[x] = tp;
 26     return;
 27 }
 28 
 29 inline void clear() {
 30     memset(e + 1, 0, tot * sizeof(int));
 31     memset(dfn + 1, 0, tot * sizeof(int));
 32     memset(fr + 1, 0, tot * sizeof(int));
 33     tp = top = num = scc_cnt = 0;
 34     return;
 35 }
 36 
 37 void tarjan(int x) {
 38     low[x] = dfn[x] = ++num;
 39     stk[++top] = x;
 40     for(int i = e[x]; i; i = edge[i].nex) {
 41         int y = edge[i].v;
 42         if(!dfn[y]) {
 43             tarjan(y);
 44             low[x] = std::min(low[x], low[y]);
 45         }
 46         else if(!fr[y]) {
 47             low[x] = std::min(low[x], dfn[y]);
 48         }
 49     }
 50     if(low[x] == dfn[x]) {
 51         ++scc_cnt;
 52         int y;
 53         do {
 54             y = stk[top];
 55             top--;
 56             fr[y] = scc_cnt;
 57         } while(y != x);
 58     }
 59     return;
 60 }
 61 
 62 void Add(int L, int R, int v, int l, int r, int &o) {
 63     if(!o) o = ++tot;
 64     if(L <= l && r <= R) {
 65         add(v, o);
 66         return;
 67     }
 68     int mid = (l + r) >> 1;
 69     if(L <= mid) Add(L, R, v, l, mid, ls[o]);
 70     if(mid < R) Add(L, R, v, mid + 1, r, rs[o]);
 71     return;
 72 }
 73 
 74 void build(int f, int l, int r, int &o) {
 75     if(!o) o = ++tot;
 76     if(f) add(f, o);
 77     if(l == r) {
 78         for(int i = 0; i < (int)v[r].size(); i++) {
 79             if(v[r][i].f) {
 80                 add(o, v[r][i].x);
 81             }
 82             else {
 83                 add(o, v[r][i].x + n);
 84             }
 85         }
 86         return;
 87     }
 88     int mid = (l + r) >> 1;
 89     build(o, l, mid, ls[o]);
 90     build(o, mid + 1, r, rs[o]);
 91     return;
 92 }
 93 
 94 inline bool check(int k) {
 95 
 96     clear();
 97     for(int i = 1; i <= n; i++) {
 98         int l = std::lower_bound(X + 1, X + xx + 1, X[A[i]] - k) - X;
 99         int r = std::upper_bound(X + 1, X + xx + 1, X[A[i]] + k) - X - 1;
100         int mid = A[i];
101         if(l < mid) {
102             Add(l, mid - 1, i, 1, xx, rt);
103         }
104         if(mid < r) {
105             Add(mid + 1, r, i, 1, xx, rt);
106         }
107         for(int j = 0; j < (int)v[mid].size(); j++) {
108             if(v[mid][j].x == i) continue;
109             if(v[mid][j].f) {
110                 add(i, v[mid][j].x);
111             }
112             else {
113                 add(i, v[mid][j].x + n);
114             }
115         }
116         l = std::lower_bound(X + 1, X + xx + 1, X[B[i]] - k) - X;
117         r = std::upper_bound(X + 1, X + xx + 1, X[B[i]] + k) - X - 1;
118         mid = B[i];
119         if(l < mid) {
120             Add(l, mid - 1, i + n, 1, xx, rt);
121         }
122         if(mid < r) {
123             Add(mid + 1, r, i + n, 1, xx, rt);
124         }
125         for(int j = 0; j < (int)v[mid].size(); j++) {
126             if(v[mid][j].x == i) continue;
127             if(v[mid][j].f) {
128                 add(i + n, v[mid][j].x);
129             }
130             else {
131                 add(i + n, v[mid][j].x + n);
132             }
133         }
134     }
135     build(0, 1, xx, rt);
136     for(int i = 1; i <= tot; i++) {
137         if(!dfn[i]) {
138             tarjan(i);
139         }
140     }
141     for(int i = 1; i <= n; i++) {
142         if(fr[i] == fr[i + n]) return 0;
143     }
144     return 1;
145 }
146 
147 int main() {
148 
149     scanf("%d", &n);
150     tot = n << 1;
151     for(int i = 1; i <= n; i++) {
152         scanf("%d%d", &A[i], &B[i]);
153         X[++xx] = A[i]; X[++xx] = B[i];
154     }
155     std::sort(X + 1, X + xx + 1);
156     xx = std::unique(X + 1, X + xx + 1) - X - 1;
157     for(int i = 1; i <= n; i++) {
158         A[i] = std::lower_bound(X + 1, X + xx + 1, A[i]) - X;
159         B[i] = std::lower_bound(X + 1, X + xx + 1, B[i]) - X;
160         v[A[i]].push_back(Node(i, 0));
161         v[B[i]].push_back(Node(i, 1));
162     }
163 
164     int l = -1, r = X[xx] - X[1];
165     while(l < r) {
166         int mid = (l + r + 1) >> 1;
167         if(check(mid)) {
168              l = mid;
169          }
170          else {
171              r = mid - 1;
172          }
173     }
174 
175     printf("%d\n", r + 1);
176     return 0;
177 }
AC代码

我这个写法不对,如果离散化了就不能暴力处理单个位置的其他边,因为可能会被卡成n²。正确的方法是不离散化或者对每个位置再用一个前后缀优化连边。

转载于:https://www.cnblogs.com/huyufeifei/p/10599853.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值