Cutting Bamboos(2019年牛客多校H题+二分+主席树)

题目链接

传送门

题意

有$n$棵竹子,然后有$q$次操作,每次操作给你$l,r,x,y$,表示对$[l,r]$区间的竹子砍$y$次,每次砍伐的长度和相等(自己定砍伐的高度$len$,该区间大于$len$的树木都要砍到$len$),问你第$x$次砍的高度是多少(注意在经过$y$次砍伐后该区间的竹子的高度都会变成$0$,询问之间互不影响)。

思路

由于在$y$次砍伐后树木高度都变为$0$,且每次砍伐的总长度都相等,因此每次砍伐的长度和为该区间内竹子高度之和除以$y$,前$x$砍伐的总高度为$xlen$,然后二分第$x$次砍伐的高度,在主席树里面找大于砍伐高度的竹子有多少棵(记为$sum1$),这些竹子的高度和为$sum2$,然后比较$sum2-sum1mid$与$x*len$的关系调整上下界。

因为生日回家了几天,咕了两场多校,写几篇水题博客假装自己有在训练~

代码

#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;

#define lson (rt<<1),L,mid
#define rson (rt<<1|1),mid + 1,R
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("/home/dillonh/CLionProjects/Dillonh/in.txt","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0)

const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 200000 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;

int n, q, cnt, l, r, x, y;
int root[maxn];
LL sum1, sum2, sum[maxn];

struct node {
    int l, r;
    LL sum1, sum2;
}tree[maxn*40];

void update(int l, int r, int& x, int y, int pos) {
    tree[++cnt] = tree[y], tree[cnt].sum1 += 1, tree[cnt].sum2 += pos, x = cnt;
    if(l == r) return;
    int mid = (l + r) >> 1;
    if(pos <= mid) update(l, mid, tree[x].l, tree[y].l, pos);
    else update(mid + 1, r, tree[x].r, tree[x].r, pos);
}

void query(int l, int r, int x, int y, double pos) {
    if(l == r) {
        if(pos - l >= eps) {
            sum1 += tree[y].sum1 - tree[x].sum1;
            sum2 += tree[y].sum2 - tree[x].sum2;
        }
        return;
    }
    int mid = (l + r) >> 1;
    if(mid - pos > eps) query(l, mid, tree[x].l, tree[y].l, pos);
    else {
        sum1 += tree[tree[y].l].sum1 - tree[tree[x].l].sum1;
        sum2 += tree[tree[y].l].sum2 - tree[tree[x].l].sum2;
        query(mid + 1, r, tree[x].r, tree[y].r, pos);
    }
}

int main() {
#ifndef ONLINE_JUDGE
    FIN;
#endif
    scanf("%d%d", &n, &q);
    for(int i = 1; i <= n; ++i) {
        scanf("%d", &x);
        sum[i] = sum[i-1] + x;
        update(0, 100000, root[i], root[i-1], x);
    }
    while(q--) {
        scanf("%d%d%d%d", &l, &r, &x, &y);
        double len = 1.0 * (sum[r] - sum[l-1]) / y * x;
        double ub = 100000.0, lb = 0.0, mid, ans = 0.0;
        for(int i = 0; i < 100; ++i) {
            mid = (ub + lb) / 2;
            sum1 = sum2 = 0;
            query(0, 100000, root[l-1], root[r], mid);
            double tot = 1.0 * (sum[r] - sum[l-1] - sum2);
            double big = 1.0 * (r - l + 1 - sum1);
            if(tot - big * mid - len > eps) {
                ans = mid;
                lb = mid;
            } else {
                ub = mid;
            }
        }
        printf("%.7f\n", ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Dillonh/p/11360196.html
今日推荐