• LA 4254 Processor (二分+贪心)


    ACM-ICPC Live Archive

      这道题搞了我两天,最终还是搞出来了!

      很容易就可以发现这题是二分,不过二分后怎么贪心就稍微有点难想了。贪心的方法其实很简单,就是尽量先把结束的早的任务先尽早的完成了。如果在给定的处理器速度下不能完成所有任务,那么这个速度就还不够。

      我的方法是用线段树填充尽量靠左的填充没利用的速度,根据能够填充的量,判断贪心是否能够做到。

    代码如下:

    View Code
      1 #define REP(i, n) for (int i = 0; i < (n); i++)
      2 
      3 #define lson l, m, rt << 1
      4 #define rson m + 1, r, rt << 1 | 1
      5 
      6 struct Task {
      7     int l, r;
      8     LL w;
      9     Task() {}
     10     Task(int _l, int _r, LL _w) : l(_l), r(_r), w(_w) {}
     11     bool operator < (const Task &x) const {
     12         if (r != x.r) return r < x.r;
     13         return l > x.l;
     14     }
     15 } task[N];
     16 LL rest[M << 2], buf[M << 2];
     17 
     18 void up(int rt) {
     19     rest[rt] = rest[rt << 1] + rest[rt << 1 | 1];
     20 }
     21 
     22 void down(int rt) {
     23     if (buf[rt]) {
     24         int ls = rt << 1, rs = rt << 1 | 1;
     25         LL val = min(buf[rt], rest[ls]);
     26         buf[rs] += val - rest[ls];
     27         rest[rs] -= val - rest[ls];
     28         buf[ls] += val;
     29         rest[ls] -= val;
     30         buf[rt] = 0;
     31     }
     32 }
     33 
     34 void build(LL val, int l, int r, int rt) {
     35     buf[rt] = 0;
     36     if (l == r) {
     37         rest[rt] = val;
     38         return ;
     39     }
     40     int m = (l + r) >> 1;
     41     build(val, lson);
     42     build(val, rson);
     43     up(rt);
     44 }
     45 
     46 LL update(LL val, int L, int R, int l, int r, int rt) {
     47     int ret = 0;
     48     if (L <= l && r <= R) {
     49         ret = min(val, rest[rt]);
     50         buf[rt] += ret;
     51         rest[rt] -= ret;
     52         return ret;
     53     }
     54     int m = (l + r) >> 1;
     55     down(rt);
     56     if (L <= m) {
     57         ret = update(val, L, R, lson);
     58         if (val - ret > 0 && m < R) {
     59             ret += update(val - ret, L, R, rson);
     60         }
     61     } else if (m < R) {
     62         ret = update(val, L, R, rson);
     63     }
     64     up(rt);
     65     return ret;
     66 }
     67 
     68 int mL, mR;
     69 
     70 void input(int n) {
     71     int l, r;
     72     LL w;
     73     mL = inf;
     74     mR = -inf;
     75     REP(i, n) {
     76         scanf("%d%d%lld", &l, &r, &w);
     77         task[i] = Task(l, r - 1, w);
     78         mL = min(mL, l);
     79         mR = max(mR, r - 1);
     80     }
     81     sort(task, task + n);
     82 }
     83 
     84 bool test(LL x, int n) {
     85     build(x, mL, mR, 1);
     86     REP(i, n) {
     87         LL tmp = update(task[i].w, task[i].l, task[i].r, mL, mR, 1);
     88         if (tmp < task[i].w) return false;
     89     }
     90     return true;
     91 }
     92 
     93 LL work(int n) {
     94     LL l = 0, r = 100000000, mk = r;
     95     while (l <= r) {
     96         LL m = (l + r) >> 1;
     97         if (test(m, n)) mk = m, r = m - 1;
     98         else l = m + 1;
     99     }
    100     return mk;
    101 }
    102 
    103 int main() {
    104     int n, T;
    105     scanf("%d", &T);
    106     while (T-- && ~scanf("%d", &n)) {
    107         input(n);
    108         printf("%lld\n", work(n));
    109     }
    110     return 0;
    111 }

      这题还可以用优先队列的方法来做,具体代码将尽快更新。

    UPD:

      用多重集来代替优先队列,代码如下:

    View Code
     1 #define MSET multiset
     2 #define ITOR iterator
     3 #define REP(i, n) for (int i = 0; i < (n); i++)
     4 
     5 typedef pair<int, int> PII;
     6 typedef vector<PII> VPII;
     7 
     8 int r[N], d[N];
     9 bool vis[N];
    10 LL w[N];
    11 VPII timeMark;
    12 
    13 void input(int n) {
    14     timeMark.clear();
    15     REP(i, n) {
    16         scanf("%d%d%lld", &r[i], &d[i], &w[i]);
    17         timeMark.PB(MPR(r[i], i));
    18         timeMark.PB(MPR(d[i], i));
    19     }
    20     sort(ALL(timeMark));
    21 }
    22 
    23 LL rest[N];
    24 MSET<PII> onTask;
    25 
    26 bool test(int x, int n) {
    27     MSET<PII>::ITOR msi;
    28     onTask.clear();
    29     REP(i, n) rest[i] = w[i], vis[i] = false;
    30     REP(i, (n << 1) - 1) {
    31         LL cur = (LL) x * (timeMark[i + 1].FI - timeMark[i].FI);
    32         int id = timeMark[i].SE;
    33         if (vis[id]) {
    34             msi = onTask.find(MPR(d[id], id));
    35             if (msi != onTask.end()) onTask.erase(msi);
    36         } else {
    37             vis[id] = true;
    38             onTask.insert(MPR(d[id], id));
    39         }
    40         while (true) {
    41             if (cur <= 0) break;
    42             if (onTask.empty()) break;
    43             id = (*onTask.begin()).SE;
    44             if (cur > rest[id]) cur -= rest[id], rest[id] = 0ll, onTask.erase(onTask.begin());
    45             else {
    46                 rest[id] -= cur, cur = 0ll;
    47                 if (rest[id] <= 0) onTask.erase(onTask.begin());
    48             }
    49         }
    50     }
    51     REP(i, n) if (rest[i]) return false;
    52     return true;
    53 }
    54 
    55 int work(int n) {
    56     int h = -1, t = 1e7 + 10, m, mk = 0;
    57     while (h <= t) {
    58         m = (h + t) >> 1;
    59         if (test(m, n)) mk = m, t = m - 1;
    60         else h = m + 1;
    61     }
    62     return mk;
    63 }
    64 
    65 int main() {
    66     int T, n;
    67     scanf("%d", &T);
    68     while (T--) {
    69         scanf("%d", &n);
    70         input(n);
    71         printf("%d\n", work(n));
    72     }
    73     return 0;
    74 }

    ——written by Lyon

  • 相关阅读:
    登录页面上的验证码的生成
    数据库操作中使用事务进行提速
    Dotnet程序集自动生成版本号
    .NET与Java的Web Services相互调用(转)
    Struts配置
    C# WebService发布与调用方法(转)
    WinCE中C#WinForm利用Web Service查询数据库(转)
    C#打包
    VS2008快捷键大全
    这些话你懂吗?
  • 原文地址:https://www.cnblogs.com/LyonLys/p/LA_4254_Lyon.html
Copyright © 2020-2023  润新知