[代码]codeforces 150c Smart Cheater

Abstract

codeforces 150c Smart Cheater

线段树 概率

Source

http://codeforces.com/problemset/problem/150/C

Solution

一开始没读懂题,以为是选一个区间,然后这个区间的所有人都不买票……

读明白的话,就是个区间求最大子段和的题目。用线段树做就好了。

之前没写过hotel那一类的题,所以写起来很费劲。果然线段树是需要深入理解和灵活运用的啊……

Code

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

#define L(x) (x<<1)
#define R(x) (x<<1|1)
#define M(x) (x>>1)

typedef long long ll;
ll a[555555];

struct snode {
    int l, r;
    ll f, fl, fr, s;
    snode() {f = fl = fr = s = 0;}
    snode(ll a, ll b, ll c, ll d): f(a), fl(b), fr(c), s(d) {}
}st[555555<<2];

void pushup(int n) {
    st[n].s = st[L(n)].s+st[R(n)].s;
    st[n].fl = max(st[L(n)].fl, st[L(n)].s+st[R(n)].fl);
    st[n].fr = max(st[R(n)].fr, st[R(n)].s+st[L(n)].fr);
    ll &res = st[n].f;
    res = max(res, st[L(n)].f);
    res = max(res, st[R(n)].f);
    res = max(res, st[L(n)].fr+st[R(n)].fl);
}

void build(int l, int r, int n) {
    st[n].l = l; st[n].r = r;
    if (l==r) {
        st[n].s = a[l];
        st[n].f = st[n].fl = st[n].fr = max(a[l], 0ll);
        return;
    }
    int m = M(l+r);
    build(l, m, L(n));
    build(m+1, r, R(n));
    pushup(n);
}

snode query(int l, int r, int n) {
    if (l<=st[n].l && r>=st[n].r) return st[n];
    int m = M(st[n].l+st[n].r);
    snode ln, rn, res;
    if (l<=m) ln = query(l, r, L(n));
    if (r>m) rn = query(l, r, R(n));
    res.s = ln.s+rn.s;
    res.fl = max(ln.fl, ln.s+rn.fl);
    res.fr = max(rn.fr, rn.s+ln.fr);
    res.f = max(ln.f, rn.f);
    if (l<=m && r>m) res.f = max(res.f, ln.fr+rn.fl);
    return res;
}

int N, M, C;
int x[555555];
int p[555555];

int main() {
    int i, j, k;
    int t = 0;
    while (cin>>N>>M>>C) {
        ++t;
        for (i = 0; i < N; ++i)
            scanf("%d", x+i);
        for (i = 1; i < N; ++i) {
            scanf("%d", p+i);
            a[i] = (x[i]-x[i-1])*50ll-1ll*p[i]*C;
        }
        build(1, N-1, 1);
        ll ans = 0;
        while (M--) {
            scanf("%d%d", &i, &j);
            ans += query(i, j-1, 1).f;
        }
        printf("%.10f\n", ans*0.01);
    }
    return 0;
}

转载于:https://www.cnblogs.com/jffifa/archive/2012/10/26/2741296.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值