zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    安装 SciPy 和 scikit-learn 升级pip 及pip基本命令表
    js修改:before、:after的内容
    初试Celery
    python中的@
    python去除空格和换行符的方法
    Beautiful 疑问小记
    http://www.oreilly.com/catalog/errataunconfirmed.csp?isbn=9780596529321
    浏览器提示框事件
    从欧几里得距离、向量、皮尔逊系数到http://guessthecorrelation.com/
    win安装NLTK出现的问题
  • 原文地址:https://www.cnblogs.com/yyf0309/p/9789102.html
Copyright © 2011-2022 走看看