BZOJ 4341 [CF253 Printer] 解题报告

乍一看这个题好像可以二分优先度搞搞。。。

实际上能不能这么搞呢。。。?

我反正不会。。。

于是开始讲我的乱搞算法:

首先肯定要把任务按照优先度排序。

用一棵在线建点的线段树维护一个时刻是否在工作。

然后就依次插入任务,记为 i,具体而言就是二分其右端点,然后令这整个区间都变成 “工作” 的状态。

在 i 被插入之前,还要检验一下在当前情况那个神秘任务的右端点是不是题中所要求的那个。

如果是,并且 i-1 的优先度和 i 的优先度不相邻或者 i 就是最优先的任务,那么就令那个神秘任务的优先度为 i 的优先度+1。

然后把这个神秘任务插入,再来考虑任务 i。

这么写完之后发现超时了。一个点要跑 2.5s 左右。

实际上到了后面,超过 10^9 的时间是一段 1,然后才是 0。

所以这里我们只需维护这个分界点就可以了。

线段树的上界就从 10^15 变成了 10^9,比原来快了一倍。

于是就可以 AC 了。

  1 #include <cstdio>
  2 #include <algorithm>
  3 using namespace std;
  4 typedef long long LL;
  5 const int N = 50000 + 5;
  6 const int M = 15000000 + 5;
  7 const int T = 1000000000;
  8  
  9 int n, root, tot, ans_p;
 10 LL end, Tend = T, owari, Ans[N];
 11  
 12 struct Segment_Tree
 13 {
 14     int l, r, sum;
 15 }h[M];
 16  
 17 struct Task
 18 {
 19     int s, t, p, id;
 20     Task (int _s = 0, int _t = 0, int _p = 0, int _id = 0) {s = _s, t = _t, p = _p, id = _id;}
 21     bool operator < (const Task a) const
 22     {
 23         return p > a.p;
 24     }
 25 }P[N];
 26  
 27 inline void Modify(int &x, int l, int r, int s, int t)
 28 {
 29     if (!x) x = ++ tot;
 30     if (l == s && r == t) h[x].sum = r - l + 1;
 31     if (h[x].sum == r - l + 1) return ;
 32     LL mid = l + r >> 1;
 33     if (t <= mid) Modify(h[x].l, l, mid, s, t);
 34         else if (s > mid) Modify(h[x].r, mid + 1, r, s, t);
 35         else Modify(h[x].l, l, mid, s, mid), Modify(h[x].r, mid + 1, r, mid + 1, t);
 36     h[x].sum = h[h[x].l].sum + h[h[x].r].sum;
 37 }
 38  
 39 inline LL Query(int x, int l, int r, int s, int t)
 40 {
 41     if (!x) return 0;
 42     if (h[x].sum == r - l + 1) return t - s + 1;
 43     if (l == s && r == t) return h[x].sum;
 44     LL mid = l + r >> 1;
 45     if (t <= mid) return Query(h[x].l, l, mid, s, t);
 46         else if (s > mid) return Query(h[x].r, mid + 1, r, s, t);
 47         else return Query(h[x].l, l, mid, s, mid) + Query(h[x].r, mid + 1, r, mid + 1, t);
 48 }
 49  
 50 inline LL Calc(Task x)
 51 {
 52     int need = x.t;
 53     int blank = T - x.s + 1 - Query(1, 0, T, x.s, T);
 54     if (blank < need) return need - blank + Tend;
 55     int l = x.s, r = T;
 56     while (l < r)
 57     {
 58         int mid = l + r >> 1;
 59         blank = mid - x.s + 1 - Query(1, 0, T, x.s, mid);
 60         if (blank < need) l = mid + 1;
 61             else r = mid;
 62     }
 63     return l;
 64 }
 65  
 66 int main()
 67 {
 68     scanf("%d", &n);
 69     for (int i = 1; i <= n; i ++)
 70     {
 71         int s, t, p;
 72         scanf("%d%d%d", &s, &t, &p);
 73         if (p == -1) p = 0;
 74         P[i] = Task(s, t, p, i);
 75     }
 76     sort(P + 1, P + n + 1);
 77     scanf("%lld", &end);
 78     Ans[P[n].id] = end;
 79     for (int i = 1; i <= n; i ++)
 80     {
 81         if (ans_p) goto deal;
 82         owari = Calc(P[n]);
 83         if (owari + 1 == end && (i == 1 || P[i].p != P[i - 1].p - 1))
 84         {
 85             ans_p = P[i].p + 1;
 86             Modify(root, 0, T, P[n].s, owari < T ? owari : T);
 87             Tend = Tend > owari ? Tend : owari;
 88         }
 89          
 90         deal :;
 91         if (i == n) continue ;
 92         owari = Calc(P[i]);
 93         Modify(root, 0, T, P[i].s, owari < T ? owari : T);
 94         Tend = Tend > owari ? Tend : owari;
 95         Ans[P[i].id] = owari + 1;
 96     }
 97     printf("%d\n", ans_p);
 98     for (int i = 1; i <= n; i ++)
 99         printf("%lld%c", Ans[i], i == n ? '\n' : ' ');
100      
101     return 0;
102 }
4341_Gromah

 

转载于:https://www.cnblogs.com/gromah/p/5005607.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值