• [可持久化权值树] Cutting Bamboos


    题意:

    给定区间, 切y次将区间内的树全切完,每次切掉的所有和相同

    切每次都是高度为h的横刀(区间高于h的值全部变为h),求第x次切的高度

    解题思路:

    第x次切的高度不知道,但是第1 - x次一共切掉的高度和剩下的高度可以O1计算而出

    可持久化权值树记录cnt和sum

    二分枚举一个高度,使得区间内所有高于此高度的权值变为此高度, 剩下的和刚才O1算出的比较即可

    在权值树上查询等同于找到一个满足题意得最左值,将该值右侧的所以值加起来即可计算剩余值

    代码:


    /*
        Zeolim - An AC a day keeps the bug away
    */
      
    //#pragma GCC optimize(2)
    //#pragma GCC ("-W1,--stack=128000000")
    #include <bits/stdc++.h>
    using namespace std;
    #define mp(x, y) make_pair(x, y)
    #define fr(x, y, z) for(int x = y; x < z; ++x)
    #define pb(x) push_back(x)
    #define mem(x, y) memset(x, y, sizeof(x))
    typedef long long ll;
    typedef unsigned long long ull;
    typedef long double ld;
    typedef std::pair <int, int> pii;
    typedef std::vector <int> vi;
    //typedef __int128 ill;
    const ld PI = acos(-1.0);
    const ld E = exp(1.0);
    const ll INF = 0x3f3f3f3f3f3f3f3f;
    const ll MOD = 386910137;
    const ull P = 13331;
    const int MAXN = 1e6 + 10;
      
    struct zxt
    {
        int root[MAXN * 20], tot = 0;
         
        struct node { int ls, rs; ll cnt, sum;}t[MAXN];
         
        void update(int l, int r, int &now, int lst, int pos)
        {
            now = ++tot, t[now] = t[lst];
            ++t[now].cnt, t[now].sum += pos;
            if(l == r) { return ; }
            int mid = (l + r) >> 1;
            if(pos <= mid) update(l, mid, t[now].ls, t[lst].ls, pos);
            else update(mid + 1, r, t[now].rs, t[lst].rs, pos);
        }
         
        ll x, y;
         
        void query(int l, int r, int now, int lst, ld pos)
        {
            if(l == r)
            {
                x += ( t[now].cnt - t[lst].cnt);
                y += ( t[now].sum - t[lst].sum);
                return ;
            }
            ll mid = (l + r) >> 1;
            if(pos <= ld(mid) )
            {
                x += ( t[t[now].rs].cnt - t[t[lst].rs].cnt);
                y += ( t[t[now].rs].sum - t[t[lst].rs].sum);
                query(l, mid, t[now].ls, t[lst].ls, pos);
            }
            else query(mid + 1, r, t[now].rs, t[lst].rs, pos);
        }
    }T;
     
    ll arr[MAXN] = {0};
     
    ll l, r, x, y, rsum;
     
    ld nowsum;
     
    int n, q;
     
    bool check(ld mid)
    {
    	T.x = 0, T.y = 0;
        T.query(1, 100000, T.root[r], T.root[l - 1], mid);
        return (T.x * mid + (rsum - T.y) < nowsum);     
    }
     
    int main()
    { 
        ios::sync_with_stdio(0);
        cin.tie(0); cout.tie(0);
         
        cin >> n >> q;
         
        for(int i = 1; i <= n; ++i)
        {
            cin >> arr[i];
            T.update(1, 100000, T.root[i], T.root[i - 1], arr[i]);
        }
         
        while(q--)
        {
            cin >> l >> r >> x >> y;
             
            rsum = T.t[T.root[r]].sum - T.t[T.root[l - 1]].sum;
             
            nowsum = ld(rsum) - ld(rsum) * ld(x) / ld(y);
             
            ld fst = 0, lst = 100000, mid;
             
            for(int i = 0; i < 100; ++i)
            {
                mid = (fst + lst) / 2.0;
                if(check(mid))
                    fst = mid;
                else
                    lst = mid;
            }
             
            cout <<fixed << setprecision(20) << mid << '
    ';
        }
     
        return 0;
    }
  • 相关阅读:
    js监听全屏的事件
    java后端发送请求
    java参数转换为javaBean对象
    Cesiumjs初学第一天
    echarts设置toolTip大小和样式问题
    楼梯式导航
    SpringMybatisMapper
    ASP.NET Session丢失的情况
    C# 生成随机数
    c#实现每隔规定时间自动执行程序代码
  • 原文地址:https://www.cnblogs.com/zeolim/p/12270342.html
Copyright © 2020-2023  润新知