51nod1287(二分/线段树区间最值&单点更新)

Posted ygeloutingyu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod1287(二分/线段树区间最值&单点更新)相关的知识,希望对你有一定的参考价值。

题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1287

 

题意:中文题诶~

 

解法1:b[i] 存储 max(a[0], ....., a[i]),显然 b 是单调不减的,所以直接二分 x,再更新 a 和 b 数组即可;

 

代码:

技术分享
 1 #include <iostream>
 2 #include <stdio.h>
 3 using namespace std;
 4 
 5 const int MAXN = 5e4 + 10;
 6 int a[MAXN], b[MAXN], x;
 7 
 8 int main(void){
 9     int n, m;
10     scanf("%d%d", &n, &m);
11     for(int i = 0; i < n; i++){
12         scanf("%d", &a[i]);
13         if(i == 0) b[i] = a[i];
14         else b[i] = max(b[i - 1], a[i]);
15     }
16     while(m--){
17         scanf("%d", &x);
18         if(x <= a[0] || x > b[n - 1]) continue;
19         int pos = lower_bound(b, b + n, x) - b;
20         a[pos - 1]++;
21         b[pos - 1] = max(b[pos - 1], a[pos - 1]);
22     }
23     for(int i = 0; i < n; i++){
24         printf("%d\n", a[i]);
25     }
26     return 0;
27 }
View Code

 

解法2:用线段树维护区间最大值,再更新一下 a 数组即可;

 

代码:

技术分享
 1 #include <iostream>
 2 #include <stdio.h>
 3 #define lson l, mid, rt << 1
 4 #define rson mid + 1, r, rt << 1 | 1
 5 using namespace std;
 6 
 7 const int MAXN = 5e4 + 10;
 8 int Max[MAXN << 2];
 9 int a[MAXN];
10 
11 void push_up(int rt){
12     Max[rt] = max(Max[rt << 1], Max[rt << 1 | 1]);
13 }
14 
15 void build(int l, int r, int rt){
16     if(l == r){
17         Max[rt] = a[l];
18         return;
19     }
20     int mid = (l + r) >> 1;
21     build(lson);
22     build(rson);
23     push_up(rt);
24 }
25 
26 void update(int p, int x, int l, int r, int rt){
27     if(l == r){
28         Max[rt] += x;
29         return;
30     }
31     int mid = (l + r) >> 1;
32     p <= mid ? update(p, x, lson) : update(p, x, rson);
33     push_up(rt);
34 }
35 
36 
37 int query(int x, int l, int r, int rt){
38     if(l == r) return l;
39     int mid = (l + r) >> 1;
40     return Max[rt << 1] >= x ? query(x, lson) : query(x, rson);
41 }
42 
43 
44 int main(void){
45     int n, m, x;
46     scanf("%d%d", &n, &m);
47     for(int i = 1; i <= n; i++){
48         scanf("%d", &a[i]);
49     }
50     build(1, n , 1);
51     while(m--){
52         scanf("%d", &x);
53         if(x > Max[1] || x <= a[1]) continue;
54         int index = query(x, 1, n, 1);
55         a[index - 1] += 1;
56         update(index - 1, 1, 1, n, 1);
57     }
58     for(int i = 1; i <= n; i++){
59         printf("%d\n", a[i]);
60     }
61     return 0;
62 }
View Code

 

以上是关于51nod1287(二分/线段树区间最值&单点更新)的主要内容,如果未能解决你的问题,请参考以下文章

51nod 1287 线段树

51NOD 1962 区间计数 单调栈+二分 / 线段树+扫描线

51NOD 1287 加农炮(不水的线段树)

hdu6070(分数规划/二分+线段树区间更新,区间最值)

HDU 1754区间最值 & SPLAY

做题51Nod1766树上的最远点对——直径&线段树