zoukankan      html  css  js  c++  java
  • AT2336 [ARC069D] Flags

    题目大意:

    (N)个标志放在一条线上,第 (i) 个标志可以放置在坐标 (x_i) 或坐标 (y_i) 上。

    (Snuke) 认为当他们中的两个之间的最小距离 (d) 更大时,标志看起来更好。

    找出 (d) 的最大可能值。

    (n<=10^4,x_i,y_i<=10^9)

    solution

    每个点只有两种选择,同时每个点选择之间会存在不合法,2-SAT 问题

    显然,答案具有二分性

    二分一个答案,然后确定那些点不能同时选,向它的对立点连边,

    如果一个点的两个位置在一个强连通分量中,那么答案就不合法

    连边是 (O(n^2)) 的,会 T

    因为每个点可以是对一个区间连边,所以可以把每个点按照位置排个序,线段树优化建图就好了

    code

    /*
    work by:Ariel_
    */
    #include<iostream>
    #include<cstdio>
    #include<stack>
    #include<algorithm>
    #include<cstring>
    #define int long long
    #define clear(x) memset(x, 0, sizeof(x))
    #define op(x) ((x) <= n ? (x) + n : (x) - n)
    #define lson rt << 1
    #define rson rt << 1 | 1
    using namespace std;
    const int N = 3e6 + 5, K = 1e4 + 5; 
    int read() {
      int x = 0, f = 1; char c = getchar();
      while(c < '0' || c > '9'){if (c == '-') f = -1;c = getchar();}
      while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();}
      return x * f;
    }
    int n, id[N], ans, cnt;
    struct FLAGS{
       int pos, id;
       bool operator<(const FLAGS& f) const { return pos < f.pos; }
       FLAGS(int pos = 0):pos(pos){};
    }flg[N];
    struct edge{int v, nxt;}e[N];
    bool cmp(FLAGS x, FLAGS y){return x.pos < y.pos;}
    int head[N], E;
    void add_edge(int u, int v) {
       e[++E] = (edge) {v, head[u]};
       head[u] = E;
    }
    namespace Seg{
       void build(int rt, int l, int r) {
        id[rt] = ++cnt;
        if (l == r) {
            add_edge(id[rt], op(flg[l].id));
            return;
         }
         int mid = (l + r) >> 1;
         build(lson, l, mid), build(rson, mid + 1, r);
         add_edge(id[rt], id[lson]), add_edge(id[rt], id[rson]);
       }
       void modify(int rt, int l, int r, int L, int R, int v) {
       	  if (L > R) return ; 
    	  int mid = (l + r) >> 1;
       	  if (l == L && r == R) add_edge(v, id[rt]);
    	  else if (R <= mid) modify(lson, l, mid, L, R, v);
    	  else if (L > mid) modify(rson, mid + 1, r, L, R, v);
    	  else modify(lson, l, mid, L, mid, v), modify(rson, mid + 1, r, mid + 1, R, v); 
       }
    }
    using namespace Seg;
    int vis[N], dfn[N], low[N], tot, sc, scc[N];
    stack<int> s;
    void tarjan(int x) {
       low[x] = dfn[x] = ++tot;
       s.push(x), vis[x] = 1;
       for (int i = head[x]; i; i = e[i].nxt) {
       	     int v = e[i].v;
       	    if (!dfn[v]) {
       	      tarjan(v);
    		  low[x] = min(low[x], low[v]);
    		}
    		else if(vis[v]) low[x] = min(dfn[v], low[x]);
       }
       int k;
       if (low[x] == dfn[x]) {
       	  sc++;
       	  do{
       	  	k = s.top(), s.pop();
       	  	scc[k] = sc, vis[k] = 0;
    	  }while(k != x);
       }
    }
    bool check(int v) {
      clear(head), clear(low), clear(dfn), clear(e), clear(vis), clear(scc);
      E = tot = cnt = 0;
      build(1, 1, cnt = 2 * n);
      int l, r;
      for (int i = 1; i <= 2 * n; i++) {
      	 l = upper_bound(flg + 1, flg + 2 * n + 1, FLAGS(flg[i].pos - v)) - flg;
      	 r = upper_bound(flg + 1, flg + 2 * n + 1, FLAGS(flg[i].pos + v - 1)) - flg - 1;
      	 modify(1, 1, 2 * n, l, i - 1, flg[i].id), modify(1, 1, 2 * n, i + 1, r, flg[i].id); 
      }
      for (int i = 1; i <= 2 * n; i++) if (!dfn[i]) tarjan(i);
      for (int i = 1; i <= n; i++) if(scc[i] == scc[i + n]) return 0;
      return 1;
    }
    signed main(){
      n = read();
      for (int i = 1; i <= n; i++) {
      	flg[i].pos = read(), flg[i + n].pos = read();
      	flg[i].id = i, flg[i + n].id = i + n;
      }
      sort(flg + 1, flg + 2 * n + 1, cmp);
      int l = 0, r = flg[2 * n].pos - flg[1].pos + 1;
      while(l <= r) {
      	 int mid = (l + r) >> 1;
      	 if (check(mid)) l = mid + 1, ans = mid; 
      	 else r = mid - 1;
      }
      printf("%lld", ans);
      puts("");
      return 0;
    }
    
  • 相关阅读:
    C语言(北京理工大学MOOC 上)
    四则运算、进制转换、变量内存分配
    C语言(挑战ACM-ICPC,DEVFORGE学编程社区)
    迭代公式求平方根
    C语言(数据结构,DEVFORGE学编程社区)
    C语言(复杂数据,DEVFORGE学编程社区)
    C语言(字符串,DEVFORGE学编程社区)
    c语言(北京理工大学mooc 下)
    华中农业大学mooc编程题
    Java通过POI读取Excel
  • 原文地址:https://www.cnblogs.com/Arielzz/p/15036304.html
Copyright © 2011-2022 走看看