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

题意:有n棵树在水平线上,给出每棵树的坐标和高度,然后向左倒的概率和向右倒的概率,和为1,然后给出了m个蘑菇的位置,每一个蘑菇都有一个魔法值,假设蘑菇被压死了,也就是在某棵树[a[i] - h[i], a[i]) 或 (a[i], a[i] + h[i]]范围内。魔法值就没有了。仅仅有生存下来的蘑菇才有魔法值,问生存下来的蘑菇的魔法值的期望。

题解:能够看到n和m的范围是1e5。而坐标范围是1e9。所以肯定要离散化,然后更新每一个区间的概率值,单点查询每一个蘑菇所在区间的概率值乘其魔法值。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
const int N = 100005;
int n, m, a[N], h[N], b[N], z[N], c[N << 2];
double tree[N << 4], flag[N << 4], pl[N], pr[N];
map<int, int> mp;

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

void build(int k, int left, int right) {
    flag[k] = 0;
    tree[k] = 1.0;
    if (left != right) {
        int mid = (left + right) / 2;
        build(k * 2, left, mid);
        build(k * 2 + 1, mid + 1, right);
    }
}

void modify(int k, int left, int right, int l1, int r1, double x) {
    if (l1 <= left && right <= r1) {
        tree[k] *= x;
        flag[k] = 1;
        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 + 1, right, l1, r1, x);
}

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

int main() {
    scanf("%d%d", &n, &m);
    mp.clear();
    int cnt = 0;
    for (int i = 1; i <= n; i++) {
        scanf("%d%d%lf%lf", &a[i], &h[i], &pl[i], &pr[i]);
        pl[i] /= 100.0, pr[i] /= 100.0;
        c[++cnt] = a[i];
        c[++cnt] = a[i] - h[i];
        c[++cnt] = a[i] + h[i];
    }
    for (int i = 1; i <= m; i++) {
        scanf("%d%d", &b[i], &z[i]);
        c[++cnt] = b[i];
    }
    sort(c + 1, c + 1 + cnt);
    cnt = unique(c + 1, c + 1 + cnt) - (c + 1);
    for (int i = 1; i <= cnt; i++)
        mp[c[i]] = i;
    build(1, 1, cnt);
    for (int i = 1; i <= n; i++) {
        modify(1, 1, cnt, mp[a[i] - h[i]], mp[a[i]] - 1, 1.0 - pl[i]);
        modify(1, 1, cnt, mp[a[i]] + 1, mp[a[i] + h[i]], 1.0 - pr[i]);
    }
    double res = 0;
    for (int i = 1; i <= m; i++)
        res += z[i] * query(1, 1, cnt, mp[b[i]]);
    printf("%lf\n", res);
    return 0;
}
时间: 2024-10-14 04:27:22

Codeforces 138C(区间更新+离散化)的相关文章

POJ 2528 Mayor&#39;s posters (线段树区间更新+离散化)

题目链接:http://poj.org/problem?id=2528 给你n块木板,每块木板有起始和终点,按顺序放置,问最终能看到几块木板. 很明显的线段树区间更新问题,每次放置木板就更新区间里的值.由于l和r范围比较大,内存就不够了,所以就用离散化的技巧 比如将1 4化为1 2,范围缩小,但是不影响答案. 写了这题之后对区间更新的理解有点加深了,重点在覆盖的理解(更新左右两个孩子节点,然后值清空),还是要多做做题目. 1 #include <iostream> 2 #include <

线段树区间更新+离散化——ZOJ 3299

对应ZOJ题目:点击打开链接 Fall the Brick Time Limit: 3000MS   Memory Limit: 32768KB   64bit IO Format: %lld & %llu Submit Status Description Now the God is very angry, so he wants to punish the lazy, greedy humans. He chooses to throw some lines of bricks (just

Codeforces 35E(区间更新)

题意:要建n个高楼,给出了每个高楼的左右区间和高度,问最后所有的高楼的轮廓包括了哪些点. 题解:这题好坑,用了n种姿势了还是一直wa,后来才直到必须加输入输出文件那句话才能过...用线段树存维护区间内最大值也就是高度,左右区间到1e9所以要离散化.因为维护的是每一段的最大值而不是点,所以划分左右子区间那里要把mid到mid+1也归到右子区间里. #include <cstdio> #include <cstring> #include <algorithm> #incl

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

POJ 2528 Mayor&#39;s posters(线段树区间染色+离散化或倒序更新)

Mayor's posters Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 59239   Accepted: 17157 Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral post

poj-----(2528)Mayor&#39;s posters(线段树区间更新及区间统计+离散化)

Mayor's posters Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 43507   Accepted: 12693 Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral post

POJ 2528 Mayor&#39;s posters (离散化+线段树区间更新)

Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral posters at all places at their whim. The city council has finally decided to build an electoral wall for

poj 2528 Mayor&#39;s posters(线段树 离散化 区间更新 贴海报)

     这个题目本来对大神来说可能是水题, 对我就不行了,昨晚非折腾到下半夜一点 搞定, 并且可以总结出 ,只有把问题想清楚,或着看人家解题报告自己把问题和代码思路 搞清楚,才能谈的上调bug,否则根本就不知道错在哪儿.说说这个题目的理解,他是如何转化为线段树问题的呢?我们知道线段树有一个区间更新的东西,每张海报的宽度不就是一个区间么?那么我们可以用一棵树中的部分结点 来表示整张海报的可视部分,也就是说每个结点只允许表示一张完整的或着不完整的海报(好几个结点才可以表示成完整的一张海报),那么如

线段树区间更新,区间统计+离散化 POJ 2528 Mayor&#39;s posters

题意:有一个很长的板子(10000000长),在上面贴n(n<=10000)张海报,问最后从外面能看到几张不同的海报. 因为板子有10000000长,直接建树肯定会爆,所以需要离散化处理,对于每张海报,有两个端点值,最后能看到几张海报跟他们的端点值的相对大小有关,跟绝对大小无关,所以就把所有海报的端点离散化处理,总共2n个端点,排序去重,对应p(p<=2n)个点.然后建树,因为p不超过20000,所以这样就可以接受了.区间更新时,因为我们只关心最外面海报的颜色有多少种,所以向下传递节点信息的时