• bzoj 1835 base 基站选址


    题目传送门

      需要高级权限的传送门

    题目大意

      有$n$个村庄坐落在一条直线上,第$i (i>1)$个村庄距离第$1$个村庄的距离为$D_i$。需要在这些村庄中建立不超过$K$个通讯基站,在第$i$个村庄建立基站的费用为$C_i$。如果在距离第$i$个村庄不超过$S_i$的范围内建立了一个通讯基站,那么就成它被覆盖了。如果第$i$个村庄没有被覆盖,则需要向他们补偿,费用为$W_i$。现在的问题是,选择基站的位置,使得总费用最小。 

      三方dp是显然的,用$f_{i, j}$表示考虑前$i$个村庄,在第$i$个村庄建立基站的最小费用。

      预处理一下,每个村庄距离不超过$S_i$的村庄区间。然后考虑用某个数据结构来维护转移。

      将这些区间按照右端点排序,当当前考虑的$i$大于这个区间的右端点的时候,那么这个区间的左端点以前的状态的转移需要加上它的赔偿费用。

      然后就做完了。时间复杂度$O(nklog n)$

    Code

      1 /**
      2  * bzoj
      3  * Problem#1835
      4  * Accepted
      5  * Time: 2468ms
      6  * Memory: 11300k
      7  */
      8 #include <algorithm>
      9 #include <iostream>
     10 #include <cstdlib>
     11 #include <cstdio>
     12 #include <queue>
     13 using namespace std;
     14 typedef bool boolean;
     15 #define ll long long
     16 
     17 const signed int inf = (signed) (~0u >> 2);
     18 const int N = 2e4 + 5, Kmx = 105;
     19 
     20 typedef class Segment {
     21     public:
     22         int l, r, cost;
     23 
     24         boolean operator < (Segment s) const {
     25             return r < s.r;
     26         }
     27 }Segment;
     28 
     29 typedef class SegTreeNode {
     30     public:
     31         int val, tg;
     32         SegTreeNode *l, *r;
     33 
     34         void pushUp() {
     35             val = (l->val < r->val) ? (l->val) : (r->val);
     36         }
     37 
     38         void pushDown() {
     39             l->val += tg, l->tg += tg;
     40             r->val += tg, r->tg += tg;
     41             tg = 0;
     42         }
     43 }SegTreeNode;
     44 
     45 SegTreeNode pool[N << 2];
     46 SegTreeNode *top;
     47 
     48 SegTreeNode* newnode() {
     49     top->val = inf, top->tg = 0;
     50     top->l = top->r = NULL;
     51     return top++;    
     52 }
     53 
     54 typedef class SegTree {
     55     public:
     56         int n;
     57         SegTreeNode* rt;
     58 
     59         SegTree() {    }
     60         SegTree(int n):n(n) {
     61             top = pool;
     62             build(rt, 1, n);
     63         }
     64 
     65         void build(SegTreeNode*& p, int l, int r) {
     66             p = newnode();
     67             if (l == r)
     68                 return;
     69             int mid = (l + r) >> 1;
     70             build(p->l, l, mid);
     71             build(p->r, mid + 1, r);
     72         }
     73 
     74         void update(SegTreeNode* p, int l, int r, int ql, int qr, int val) {
     75             if (ql == l && r == qr) {
     76                 p->val += val;
     77                 p->tg += val;
     78                 return;
     79             }
     80             if (p->tg)
     81                 p->pushDown();
     82             int mid = (l + r) >> 1;
     83             if (qr <= mid)
     84                 update(p->l, l, mid, ql, qr, val);
     85             else if (ql > mid)
     86                 update(p->r, mid + 1, r, ql, qr, val);
     87             else {
     88                 update(p->l, l, mid, ql, mid, val);
     89                 update(p->r, mid + 1, r, mid + 1, qr, val);
     90             }
     91             p->pushUp();
     92         }
     93 
     94         void update(SegTreeNode* p, int l, int r, int idx, int val) {
     95             if (l == r) {
     96                 p->val = val;
     97                 return;
     98             }
     99             if (p->tg)
    100                 p->pushDown();
    101             int mid = (l + r) >> 1;
    102             if (idx <= mid)
    103                 update(p->l, l, mid, idx, val);
    104             else
    105                 update(p->r, mid + 1, r, idx, val);
    106             p->pushUp();
    107         }
    108 
    109         int query() {
    110             return rt->val;
    111         }
    112 
    113         void update(int l, int r, int val) {
    114             if (l > r)
    115                 return;
    116             update(rt, 1, n, l, r, val);
    117         }
    118         
    119         void update(int p, int val) {
    120             update(rt, 1, n, p, val);
    121         }
    122 }SegTree;
    123 
    124 int n, K, tp = 0;
    125 int dist[N], cost[N], rang[N];
    126 int comp[N];
    127 int f[Kmx][N];
    128 Segment sgs[N];
    129 SegTree st;
    130 
    131 inline void init() {
    132     scanf("%d%d", &n, &K);
    133     dist[1] = 0;
    134     for (int i = 2; i <= n; i++)
    135         scanf("%d", dist + i);
    136     for (int i = 1; i <= n; i++)
    137         scanf("%d", cost + i);
    138     for (int i = 1; i <= n; i++)
    139         scanf("%d", rang + i);
    140     for (int i = 1; i <= n; i++)
    141         scanf("%d", comp + i);
    142 }
    143 
    144 int res = 0;
    145 inline void solve() {
    146     for (int i = 1; i <= n; i++) {
    147         int l = dist[i] - rang[i], r = dist[i] + rang[i];
    148         sgs[i].l = lower_bound(dist + 1, dist + i + 1, l) - dist;
    149         sgs[i].r = upper_bound(dist + i, dist + n + 1, r) - dist - 1;
    150         sgs[i].cost = comp[i];
    151     }
    152     
    153     sort(sgs + 1, sgs + n + 1);
    154 
    155     for (int i = 1; i <= n; i++)
    156         res += comp[i];
    157     if (!K) {
    158         printf("%d", res);
    159         return;
    160     }
    161     
    162     int costs = 0;
    163     Segment* p = sgs + 1, *ped = sgs + n + 1;
    164     for (int i = 1; i <= n; i++) {
    165         f[1][i] = costs + cost[i];
    166         while (p != ped && p->r <= i)
    167             costs += p->cost, p++;
    168     }
    169 
    170     for (int k = 1; k <= K; k++) {
    171         st = SegTree(n);
    172         p = sgs + 1;
    173         for (int i = 1; i <= n; i++) {
    174             f[k + 1][i] = st.query() + cost[i];
    175             while (p != ped && p->r <= i)
    176                 st.update(1, p->l - 1, p->cost), p++;
    177             st.update(i, f[k][i]);
    178         }
    179         res = min(res, st.query());
    180     }
    181     printf("%d", res);
    182 }
    183 
    184 int main() {
    185     init();
    186     solve();
    187     return 0;
    188 }
  • 相关阅读:
    如何:为 Silverlight 客户端生成双工服务
    Microsoft Sync Framework 2.1 软件开发包 (SDK)
    Windows 下的安装phpMoAdmin
    asp.net安全检测工具 Padding Oracle 检测
    HTTP Basic Authentication for RESTFul Service
    Windows系统性能分析
    Windows Server AppFabric Management Pack for Operations Manager 2007
    Mongo Database 性能优化
    服务器未能识别 HTTP 标头 SOAPAction 的值
    TCP WAIT状态及其对繁忙的服务器的影响
  • 原文地址:https://www.cnblogs.com/yyf0309/p/9789102.html
Copyright © 2020-2023  润新知