线段树(单点更新) HDOJ 2795 Billboard

题目传送门

 1 /*
 2     主要利用线段树求区间最值,sum[]代表位置可用空间
 3     每次找到最大值的位置
 4     功能:查询最靠前能容纳广告的位置
 5 */
 6 #include <cstdio>
 7 #include <cstring>
 8 #include <algorithm>
 9 #define lson l, m, rt << 1
10 #define rson m+1, r, rt << 1 | 1
11
12 const int MAX_N = 2000000 + 10;
13 int w[MAX_N];
14 int num[MAX_N];
15 int sum[MAX_N << 2];
16 int n, h, W;
17
18 void maxsum(int rt)
19 {
20     sum[rt] = std::max (sum[rt << 1], sum[rt << 1 | 1]);
21 }
22
23 void build(int l, int r, int rt)
24 {
25     sum[rt] = W;
26     if (l == r) return ;
27     int m = (l + r) >> 1;
28     build (lson);
29     build (rson);
30 }
31
32 int query(int p, int l, int r, int rt)
33 {
34     if (l == r)
35     {
36         sum[rt] -= p;        //如果可以用,更新sum,update在query里做了
37         return l;            //返回该位置
38     }
39     int m = (l + r) >> 1;
40     int ans;
41     if (p <= sum[rt << 1])        //如果p小于左孩子的最大值,则往左边下去
42         ans = query (p, lson);
43     else
44         ans = query (p, rson);
45     maxsum (rt);
46
47     return ans;
48 }
49
50 int main(void)        //HDOJ 2795 Billboard
51 {
52     //freopen ("inD.txt", "r", stdin);
53
54     while (~scanf ("%d%d%d", &h, &W, &n))
55     {
56         if (h > n)        // h <= n
57             h = n;
58
59         build (1, h, 1);
60
61         int x;
62         while (n--)
63         {
64             scanf ("%d", &x);
65             if (x > sum[1])    printf ("%d\n", -1);    //所有位置的最大值
66             else    printf ("%d\n", query(x, 1, h, 1));
67         }
68     }
69
70     return 0;
71 }
时间: 2024-10-27 08:53:59

线段树(单点更新) HDOJ 2795 Billboard的相关文章

线段树(单点更新) HDOJ 4288 Coder

题目传送门 1 #include <cstdio> 2 #include <cstring> 3 #define lson l, m, rt << 1 4 #define rson m + 1, r, rt << 1 | 1 5 6 const int MAX_N = 500000 + 10; 7 int sum[MAX_N << 2]; 8 9 void pushup(int rt) 10 { 11 if (rt >> 1 % 5

HDU 2795 Billboard (线段树单点更新)

题意:h,w,n:有一个h*w尺寸的木板,n张1*wi的海报,贴海报的位置尽量高,尽量往左,问每张海报贴的高度 看到1 <= h,w <= 10^9; 1 <= n <= 200,000,应该就是线段树了. 关键在怎么建树,这里我们对h进行分割,每个高度都有等长的w,我们从上往下贴,如果当前高度 (在同一高度上l==r)的长度可以满足wi则可以贴,否则继续往下寻找. #include <iostream> #include <stdio.h> #includ

【线段树四】HDU 2795 Billboard

BillboardTime Limit: 20000/8000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 9045    Accepted Submission(s): 4021 Problem Description At the entrance to the university, there is a huge rectangular billboard of siz

POJ训练计划2828_Buy Tickets(线段树/单点更新)

解题报告 题意: 插队完的顺序. 思路: 倒着处理数据,第i个人占据第j=pos[i]+1个的空位. 线段树维护区间空位信息. #include <iostream> #include <cstdio> #include <cstring> using namespace std; struct node { int x,v; } num[201000]; int sum[1000000],ans[201000]; void cbtree(int rt,int l,in

HDU2852_KiKi&#39;s K-Number(线段树/单点更新)

解题报告 题目传送门 题意: 意思很好理解. 思路: 每次操作是100000次,数据大小100000,又是多组输入.普通模拟肯定不行. 线段树结点记录区间里存在数字的个数,加点删点操作就让该点个数+1,判断x存在就查询[1,x]区间的个数和[1,x-1]的个数. 求x之后第k大的数就先确定小于x的个数t,第t+k小的数就是要求的. #include <iostream> #include <cstdio> #include <cstring> using namespa

POJ3264_Balanced Lineup(线段树/单点更新)

解题报告 题意: 求区间内最大值和最小值的差值. 思路: 裸线段树,我的线段树第一发.区间最值. #include <iostream> #include <cstring> #include <cstdio> #define inf 99999999 #define LL long long using namespace std; LL minn[201000],maxx[201000]; void update(LL root,LL l,LL r,LL p,LL

HDU1166_敌兵布阵(线段树/单点更新)

解题报告 题意: 略 思路: 线段树单点增减和区间求和. #include <iostream> #include <cstring> #include <cstdio> #define LL long long using namespace std; int sum[201000]; void update(int root,int l,int r,int p,int v) { int mid=(l+r)/2; if(l==r)sum[root]+=v; else

HDU1754_I Hate It(线段树/单点更新)

解题报告 题意: 略 思路: 单点替换,区间最值 #include <iostream> #include <cstring> #include <cstdio> #define inf 99999999 using namespace std; int maxx[808000]; void update(int root,int l,int r,int p,int v) { int mid=(l+r)/2; if(l==r)maxx[root]=v; else if(

Uva 12299 RMQ with Shifts(线段树 + 单点更新 )

Uva 12299 RMQ with Shifts (线段树 + 单点更新) 题意: 对于给定的序列 x[i]给出一个操作 shift(a,b,c,d,e) 对应的是将 x[a]与x[b] x[b]与x[c] 这样相邻的两两交换For example, if A={6, 2, 4, 8, 5, 1, 4}then shift(2, 4, 5, 7) yields {6, 8, 4, 5, 4, 1, 2}. After that,shift(1, 2) yields {8, 6, 4, 5, 4