• 【AtCoder Grand Contest 001F】Wide Swap [线段树][拓扑]


    Wide Swap

    Time Limit: 50 Sec  Memory Limit: 512 MB

    Description

      

    Input

      

    Output

      

    Sample Input

      8 3
      4 5 7 8 3 1 2 6

    Sample Output

      1
      2
      6
      7
      5
      3
      4
      8

    HINT

      

    Solution

      首先,直接做难度系数较高,假设原序列为a,我们考虑设一个pp[a_i] = i,即将题目中的权值与下标调换

      那么显然,要令a字典序最小,只要让p字典序最小即可。因为“权值小的尽量前”“前面的权值尽量小”是一个意思。

      现在操作转化为:相邻元素权值差>=k的可以换顺序。

      考虑一个暴力怎么做,显然是 i后面的所有 j 比,如果 abs(p_i - p_j) < k,则 i 和 j 的相对顺序就确定了, 连一条 p_i -> p_j 的边。

      连边之后跑一边拓扑即可。

      显然复杂度在于连边,因为这样暴力会有很多无用边。比如A->B, B->C, A->C,这条A->C显然无用

      我们考虑如何删掉 A->C 这种边。

      倒着加入,显然 p_i 连向 (p_i-k, p_i)∪(p_i, p_i+k)。我们只需要分别连向两个区间中下标最小的那一个即可。用线段树维护一下区间最小值

    Code

      1 #include<iostream>
      2 #include<string>
      3 #include<algorithm>
      4 #include<cstdio>
      5 #include<cstring>
      6 #include<cstdlib>
      7 #include<cmath>
      8 #include<queue>
      9 using namespace std;
     10 typedef long long s64;
     11 
     12 #define next nxt
     13 const int ONE = 1000005;
     14 const int INF = 2147483640;
     15 
     16 int get()
     17 {
     18         int res = 1, Q = 1; char c;
     19         while( (c = getchar()) < 48 || c > 57)
     20             if(c == '-') Q = -1;
     21         if(Q) res = c - 48;
     22         while( (c = getchar()) >= 48 && c <= 57)
     23             res = res * 10 + c - 48;
     24         return res * Q;
     25 }
     26 
     27 int n, k;
     28 int A[ONE], p[ONE];
     29 int next[ONE], first[ONE], go[ONE], Input[ONE], tot;
     30 priority_queue <int, vector <int>, greater <int> > q;
     31 
     32 int res = INF;
     33 namespace Seg
     34 {
     35         struct power {int val;} Node[ONE * 4];
     36         void Build(int i, int l, int r)
     37         {
     38             Node[i].val = INF;
     39             if(l == r) return;
     40             int mid = l + r >> 1;
     41             Build(i << 1, l, mid), Build(i << 1 | 1, mid + 1, r);
     42         }
     43 
     44         void Update(int i, int l, int r, int L, int x)
     45         {
     46             if(L <= l && r <= L)
     47             {
     48                 Node[i].val = x;
     49                 return;
     50             }
     51             int mid = l + r >> 1;
     52             if(L <= mid) Update(i << 1, l, mid, L, x);
     53             else Update(i << 1 | 1, mid + 1, r, L, x);
     54             Node[i].val = min(Node[i << 1].val, Node[i << 1 | 1].val);
     55         }
     56 
     57         void Query(int i, int l, int r, int L, int R)
     58         {
     59             if(L > R) return;
     60             if(L <= l && r <= R)
     61             {
     62                 res = min(res, Node[i].val);
     63                 return;
     64             }
     65             int mid = l + r >> 1;
     66             if(L <= mid) Query(i << 1, l, mid, L, R);
     67             if(mid + 1 <= R) Query(i << 1 | 1, mid + 1, r, L, R);
     68         }
     69 }
     70 
     71 void Add(int u, int v)
     72 {
     73         Input[v]++, next[++tot] = first[u], first[u] = tot, go[tot] = v;
     74 }
     75 
     76 void Deal()
     77 {
     78         int now = 0;
     79         for(int i = 1; i <= n; i++)
     80             if(!Input[i]) q.push(i);
     81         while(!q.empty())
     82         {
     83             int u = q.top(); q.pop();
     84             A[u] = ++now;
     85             for(int e = first[u]; e; e = next[e])
     86             {
     87                 int v = go[e];
     88                 if(--Input[v] == 0) q.push(v);
     89             }
     90         }
     91         for(int i = 1; i <= n; i++) printf("%d
    ", A[i]);
     92 }
     93 
     94 int main()
     95 {
     96         n = get(), k = get();
     97         for(int i = 1; i <= n; i++) p[get()] = i;
     98 
     99         Seg::Build(1, 1, n);
    100         for(int i = n; i >= 1; i--)
    101         {
    102             res = INF, Seg::Query(1, 1, n, p[i] + 1, min(p[i] + k - 1, n));
    103             if(res != INF) Add(p[i], p[res]);
    104 
    105             res = INF, Seg::Query(1, 1, n, max(1, p[i] - k + 1), p[i] - 1);
    106             if(res != INF) Add(p[i], p[res]);
    107 
    108             Seg::Update(1, 1, n, p[i], i);
    109         }
    110 
    111         Deal();
    112 }
    View Code
  • 相关阅读:
    access remote libvirtd
    python中获取当前所有的logger
    python标准库xml.etree.ElementTree的bug
    python Requests库在处理response时的一些陷阱
    Ubuntu12.04下安装Subversion并进行配置
    命令行打包war包
    Ubuntu12.04安装MariaDB并修改字符集为UTF-8
    Windows下Navicat远程连接Linux下MySQL服务器错误1130
    解决ubuntu下eth0不显示
    解决Ubuntu12.04下rpcbind: cannot open '/var/run/rpcbind/rpcbind.xdr' file for reading
  • 原文地址:https://www.cnblogs.com/BearChild/p/7895719.html
Copyright © 2020-2023  润新知