Codeforces 35E(区间更新)

题意:要建n个高楼,给出了每个高楼的左右区间和高度,问最后所有的高楼的轮廓包括了哪些点。

题解:这题好坑,用了n种姿势了还是一直wa,后来才直到必须加输入输出文件那句话才能过。。。用线段树存维护区间内最大值也就是高度,左右区间到1e9所以要离散化。因为维护的是每一段的最大值而不是点,所以划分左右子区间那里要把mid到mid+1也归到右子区间里。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
const int N = 100005;
int n, a[N << 1], h[N], l[N], r[N], hh;
int tree[N << 4], res[N << 3][2];
map<int, int> mp;

void pushdown(int k) {
    if (tree[k]) {
        tree[k * 2] = max(tree[k * 2], tree[k]);
        tree[k * 2 + 1] = max(tree[k * 2 + 1], tree[k]);
        tree[k] = 0;
    }
}

void modify(int k, int left, int right, int l1, int r1, int x) {
    if (l1 <= left && right <= r1) {
        tree[k] = max(tree[k], x);
        return;
    }
    pushdown(k);
    int mid = (left + right) / 2;
    if (l1 < mid)
        modify(k * 2, left, mid, l1, r1, x);
    if (r1 > mid)
        modify(k * 2 + 1, mid, right, l1, r1, x);
}

void query(int k, int left, int right, int l1, int r1) {
    if (left + 1 == right) {
        hh = tree[k];
        return;
    }
    pushdown(k);
    int mid = (left + right) / 2;
    if (l1 < mid)
        query(k * 2, left, mid, l1, r1);
    else
        query(k * 2 + 1, mid, right, l1, r1);
}

int main() {
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    scanf("%d", &n);
    memset(tree, 0, sizeof(tree));
    mp.clear();
    int cnt = 0;
    for (int i = 1; i <= n; i++) {
        scanf("%d%d%d", &h[i], &l[i], &r[i]);
        a[cnt++] = l[i];
        a[cnt++] = r[i];
    }
    sort(a, a + cnt);
    cnt = unique(a, a + cnt) - a;
    for (int i = 0; i < cnt; i++)
        mp[a[i]] = i;

    for (int i = 1; i <= n; i++)
        modify(1, 0, cnt - 1, mp[l[i]], mp[r[i]], h[i]);
    int num = 0, curh = 0;
    for (int i = 0; i < cnt - 1; i++) {
        query(1, 0, cnt - 1, i, i + 1);
        if (hh != curh) {
            res[num][0] = a[i];
            res[num++][1] = curh;
            res[num][0] = a[i];
            res[num++][1] = hh;
            curh = hh;
        }
    }
    if (curh) {
        res[num][0] = a[cnt - 1];
        res[num++][1] = curh;
        res[num][0] = a[cnt - 1];
        res[num++][1] = 0;
    }
    printf("%d\n", num);
    for (int i = 0; i < num; i++)
        printf("%d %d\n", res[i][0], res[i][1]);
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-05 16:45:38

Codeforces 35E(区间更新)的相关文章

Codeforces 138C(区间更新+离散化)

题意:有n棵树在水平线上,给出每棵树的坐标和高度,然后向左倒的概率和向右倒的概率,和为1,然后给出了m个蘑菇的位置,每一个蘑菇都有一个魔法值,假设蘑菇被压死了,也就是在某棵树[a[i] - h[i], a[i]) 或 (a[i], a[i] + h[i]]范围内.魔法值就没有了.仅仅有生存下来的蘑菇才有魔法值,问生存下来的蘑菇的魔法值的期望. 题解:能够看到n和m的范围是1e5.而坐标范围是1e9.所以肯定要离散化,然后更新每一个区间的概率值,单点查询每一个蘑菇所在区间的概率值乘其魔法值. #i

CodeForces 52C Circular RMQ(区间循环线段树,区间更新,区间求和)

转载请注明出处:http://blog.csdn.net/u012860063 题目链接:http://codeforces.com/problemset/problem/52/C You are given circular array a0,?a1,?...,?an?-?1. There are two types of operations with it: inc(lf,?rg,?v) - this operation increases each element on the segm

CodeForces 444C 节点更新求变化值的和

http://vjudge.net/problem/viewProblem.action?id=51622 题目大意: 给定一列n个数字,最初赋予值1到n 两个操作:1.将区间[l,r]内的数改为x,则这区间中所有数的改变值进行求和,即ans=abs(a[l]-x)+abs[a[l+1]-x).....abs(a[r]-x),但不要求输出 2.需要将刚才要求得到的区间改变值输出出来 这里我们利用一个color[]数组相当于给这堆数进行染色,当某个区间内的赋予的值相等时,我们可以看做有一个相同的c

HDU 1689 Just a Hook 线段树区间更新求和

点击打开链接 Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 18894    Accepted Submission(s): 9483 Problem Description In the game of DotA, Pudge's meat hook is actually the most horrible

hdu 4970 树状数组区间更新 思维题

http://acm.hdu.edu.cn/showproblem.php?pid=4970 好像还没有用树状数组写过区间更新,但是树状数组的确比线段树快很多,不知道跟ZKW线段树比效率怎么样: 先贴个模板: #include <cstdio> const int MAXN = 1024; int B[MAXN], C[MAXN]; #define LOWBIT(x) ((x)&(-(x))) void bit_update(int *a, int p, int d) { for (

51nod_1199 树的先跟遍历+区间更新树状数组

题目是中文,所以不讲题意 做法顺序如下: 使用先跟遍历,把整棵树平铺到一维平面中 使用自己整的区间更新树状数组模板进行相关操作. http://www.cnblogs.com/rikka/p/7359185.html 放代码如下: 1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 6 /* 7 *常量MAXN用于设定树状数组的尺寸大小 8 */ 9 const long long MAXN=500233; 10 class TreeL

HDU 1556 Color the ball(线段树:区间更新)

http://acm.hdu.edu.cn/showproblem.php?pid=1556 题意: N个气球,每次[a,b]之间的气球涂一次色,统计每个气球涂色的次数. 思路: 这道题目用树状数组和线段树都可以,拿这道题来入门一下线段树的区间更新. 1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 6 const int maxn = 1000

hdu 1698(线段树区间更新)

Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 30080    Accepted Submission(s): 14859 Problem Description In the game of DotA, Pudge's meat hook is actually the most horrible thing

POJ 3468 A Simple Problem with Integers(树状数组区间更新)

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 97217   Accepted: 30358 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of