2017-2018 ACM-ICPC, NEERC, Southern Subregional Contest (Online Mirror, ACM-ICPC Rules, Teams Prefer...

题目大意:给一个长度为n的数列,划分成多个部分,每一个部分长度要大于等于K,定义每个部分的质量差是这部分的最大值减去最小值,求最优划分后,全局的质量差最小是多少。

题目分析:二分答案,check

    dp来check,dp[i] 代表 i这个位置可以作为一个区间的结尾,如果 i - 1 可以作为结尾, 那么就可以更新 i 作为开头的结尾位置, [l,r] 区间dp值赋为1,线段树,check dp[n]是否唯一。

 1 #include<bits/stdc++.h>
 2 #define lson l, m, rt << 1
 3 #define rson m + 1, r, rt << 1 | 1
 4 #define maxn 300010
 5 using namespace std;
 6 int a[maxn], n, k;
 7 bool vis[maxn << 2], lazy[maxn << 2];
 8 void build(int l,int r,int rt){
 9     vis[rt] = false, lazy[rt] = false;
10     if(l == r){
11         return;
12     }
13     int m = (l + r) >> 1;
14     build(lson);
15     build(rson);
16 }
17 void pushdown(int rt){
18     if(lazy[rt]){
19         lazy[rt << 1] = true;
20         lazy[rt << 1 | 1] = true;
21         vis[rt << 1] = true;
22         vis[rt << 1 | 1] = true;
23         lazy[rt] = false;
24         return;
25     }
26 }
27 void update(int L,int R,int l,int r,int rt){
28     if(L <= l && R >= r){
29         vis[rt] = true;
30         lazy[rt] = true;
31         return;
32     }
33     pushdown(rt);
34     int m = (l + r) >> 1;
35     if(L <= m)
36         update(L, R, lson);
37     if(R  > m)
38         update(L, R, rson);
39 }
40 bool query(int pos,int l,int r,int rt){
41     if(l == r) return vis[rt];
42     pushdown(rt);
43     int m = (l + r) >> 1;
44     if(pos <= l) return query(pos,lson);
45     else return query(pos, rson);
46 }
47 bool ok(int x){
48     int now, step, p, cur;
49     p = 1;
50     build(1,n,1);
51     for(int i = 1; i < n; i ++){
52         now = upper_bound(a + 1, a + 1 + n, a[i] + x) - a;
53         now --;
54         cur = i + k - 1;
55         if(cur <= now && (i == 1 || query(i - 1, 1, n, 1))){
56             update(cur, now, 1, n, 1);
57         }
58     }
59     return query(n,1,n,1);
60 }
61 int main(){    
62     cin >> n >> k;
63     for(int i = 1; i <= n; i ++) cin >> a[i];
64     sort(a + 1, a + 1 + n);
65     int l = 0, r = 1000000000, mid, res;
66     while(l <= r){
67         mid = (l + r) >> 1;
68         if(ok(mid)){
69             r = mid - 1;
70             res = mid;
71         }
72         else 
73             l = mid + 1;
74     } 
75     cout << res;
76     return 0;
77 }

 

转载于:https://www.cnblogs.com/poler/p/7710404.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值