zoukankan      html  css  js  c++  java
  • Luogu 3620 数据备份

    Solution

    很显然, 最优情况肯定是相邻两个相连 。

    然后模型就跟 Luogu1484 类似了。

    把两个房子 看成一个坑 (参考 Luogu1484), 选取 $k$ 个不相邻的坑, 使得权值最小。

    Luogu1484 则是 选取 至多 $k$ 个不相邻坑,  使得权值最大。

    先考虑简单问题:

    当$k= 1$时, 肯定是选择 最大 的$a[i]$ 

    当$k= 2$时, 仅有两种情况  选 最大的 $a[i]$ 和 不相邻的 $a[j]$ 或者 $a[i+1]+a[i-1]$

       我们先选了最大的$a[i]$

       那么怎么样才能让下一个找到的最大的 $a[j]$ 是满足条件的解呢?

      我们把 $a[i - 1]$ 和 $a[i + 1]$ 删去, 然后把 $a[i]$改为 $a[i + 1] + a[i - 1] - a[i]$,这样就满足了肯定不会 单独选到 $a[i + 1]或a[i-1]$。

      并且我们若想要选$a[i+1]和a[i-1]$且不选$a[i]$ 只需要再选一次$a[i]$即可。

    在$k$更大的情况下同样适用。

    然后就用链表存储 $nxt$ 与 $pre$, $Set$ 维护 最大值/ 最小值。

    Code

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<set>
     5 #define rd read()
     6 #define ll long long
     7 using namespace std;
     8 typedef pair<ll, int> P;
     9 
    10 const int N = 1e5 + 5;
    11 const ll inf = 1e10;
    12 
    13 int n, k;
    14 int nxt[N], pre[N];
    15 ll a[N], ans;
    16 set<P> st;
    17 
    18 int read() {
    19     int X = 0, p = 1; char c = getchar();
    20     for (; c > '9' || c < '0'; c = getchar())
    21         if (c == '-') p = -1;
    22     for (; c >= '0' && c <= '9'; c = getchar())
    23         X = X * 10 + c - '0';
    24     return X * p;
    25 }
    26 
    27 void del(int x) {
    28     nxt[pre[x]] = nxt[x];
    29     pre[nxt[x]] = pre[x];
    30 }
    31 
    32 int main()
    33 {
    34     n = rd; k = rd;
    35     for (int i = 1; i <= n; ++i) 
    36         a[i] = rd;
    37     n--;
    38     for (int i = 1; i <= n; ++i)
    39         a[i] = a[i + 1] - a[i];
    40     for (int i = 1; i <= n; ++i)
    41         nxt[i] = i + 1, pre[i] = i - 1;
    42     for (int i = 1; i <= n; ++i)
    43         st.insert(P(a[i], i));
    44     a[0] = a[n + 1] = inf;
    45     set<P> :: iterator it;
    46     for (; k; --k) {
    47         it = st.begin();
    48         P tp = *it;
    49         int x = tp.second; ll y = a[x];
    50         ll t = a[pre[x]] + a[nxt[x]] - y;
    51         a[x] = t; ans += y;
    52         st.insert(P(t, x));
    53         st.erase(P(y, x));
    54         if (pre[x])
    55             st.erase(P(a[pre[x]], pre[x])), del(pre[x]);
    56         if (nxt[x] && nxt[x] != n + 1)
    57             st.erase(P(a[nxt[x]], nxt[x])), del(nxt[x]);
    58     }
    59     printf("%lld
    ", ans);
    60 }
    View Code
  • 相关阅读:
    Ansible批量更新远程主机用户密码
    国外程序员推荐:每个程序员都应该读的非编程书
    FindFriendsServer服务搭建
    Android JNI HelloWorld实现
    2014年4月读书单
    jQuery 之父:每天写代码
    QT210 Android4.0源码编译和烧录文档整理
    Android系统分区理解及分区目录细解
    Android组件Spinner使用
    使用事件驱动模型实现高效稳定的网络服务器程序
  • 原文地址:https://www.cnblogs.com/cychester/p/9703408.html
Copyright © 2011-2022 走看看