Escape from the Hell

Escape from the Hell

[I Asia 2016]

Preference is easy to show better the difference between the large

For the last bottle we can enumerate

Enumeration last bottle, and then eliminate its impact on Fenwick tree, then the tree line check whether the situation appears to be caught up, that query interval minimum.

We need to use two tree line, because when half a bottle found at the last position behind the tree line segment need to eliminate the influence of the last bottle.

Special attention when the difference is negative when no prefix and monotonicity, so monotonous increase in half to two minutes interval.

#include <bits/stdc++.h>
 
#define ll long long
using namespace std;
const int maxn = 1e5 + 7;
const ll inf = 0x3f3f3f3f3f3f3f3f;
int n;
int C[maxn];
struct node {
    int a, b;
} s[maxn];
 
bool cmp(node x, node y) {
    return x.a - x.b > y.a - y.b;
}
 
ll c[maxn];
ll sum[maxn];
struct tree {
    int l, r;
    ll min1, min2;
} t[maxn << 2];
 
int lowbit(int x) {
    return x & (-x);
}
 
ll getsum(int i) {
    ll res = 0;
    while (i > 0) {
        res += c[i];
        i -= lowbit(i);
    }
    return res;
}
 
void update(int i, ll val) {
    while (i < maxn) {
        c[i] += val;
        i += lowbit(i);
    }
}
 
void build(int p, int l, int r) {
    t[p].l = l, t[p].r = r;
    if (l == r) {
        t[p].min1 = getsum(l) - sum[l];
        t[p].min2 = getsum(l) - sum[l - 1];
        return;
    }
    int mid = (l + r) >> 1;
    build(p << 1, l, mid);
    build(p << 1 | 1, mid + 1, r);
    t[p].min1 = min(t[p << 1].min1, t[p << 1 | 1].min1);
    t[p].min2 = min(t[p << 1].min2, t[p << 1 | 1].min2);
}
 
ll ask1(int p, int l, int r) {
    if (l <= t[p].l && r >= t[p].r) return t[p].min1;
    int mid = (t[p].l + t[p].r) >> 1;
    ll val = inf;
    if (l <= mid) val = min(val, ask1(p << 1, l, r));
    if (r > mid) val = min(val, ask1(p << 1 | 1, l, r));
    return val;
}
 
ll ask2(int p, int l, int r) {
    if (l <= t[p].l && r >= t[p].r) return t[p].min2;
    int mid = (t[p].l + t[p].r) >> 1;
    ll val = inf;
    if (l <= mid) val = min(val, ask2(p << 1, l, r));
    if (r > mid) val = min(val, ask2(p << 1 | 1, l, r));
    return val;
}
 
int erfen(int z, int y, ll x) {
    int l = z, r = y;
    while (l < r) {
        int mid = (l + r) >> 1;
        if (getsum(mid) >= x)r = mid;
        else l = mid + 1;
    }
    return l;
}
 
void dubug() {
    for (int i = 1; i <= n; ++i) {
        cout << ask1(1, i, i) << "    " << ask2(1, i, i) << endl;
    }
}
 
int main() {
    ll L;
    scanf("%d%lld", &n, &L);
    for (int i = 1; i <= n; ++i) {
        scanf("%d%d", &s[i].a, &s[i].b);
    }
    sort(s + 1, s + 1 + n, cmp);
    int k=-1;
    for (int i = 1; i <= n; ++i) {
        if(s[i].a-s[i].b>=0) update(i, s[i].a - s[i].b);
        else if(k==-1){
            k=i-1;
        }
        scanf("%d", &C[i]);
        sum[i] = sum[i - 1] + C[i];
    }
    if(k==-1) k=n;
    build(1, 1, n);
    int minn = n + 1;
    for (int i = 1; i <= n; ++i) {
        if(s[i].a-s[i].b>0) update(i, s[i].b - s[i].a);
        int pp = erfen(1, k + 1, L - s[i].a);
        if (pp != k + 1) {
            if (pp < i) {
                if (ask1(1, 1, pp) > 0) {
                    minn = min(minn, pp + 1);
                }
            } else {
                if (i==1||ask1(1, 1, i - 1) > 0) {
                    if (pp==1||ask2(1, i + 1, pp) - (s[i].a - s[i].b) > 0) {
                        minn = min(minn, pp);
                    }
                }
            }
        }
        if(s[i].a-s[i].b>0)
        update(i, s[i].a - s[i].b);
    }
    if (minn == n + 1) {
        printf("-1\n");
    } else {
        printf("%d\n", minn);
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/smallocean/p/11518434.html