zoukankan      html  css  js  c++  java
  • CF-557C Arthur and Table 权值线段树

    Arthur and Table

    题意

    一个桌子有n个腿,每个腿都有一个高度,当且仅当最高的腿的数量大于桌子腿数量的一半时,桌子才是稳定的。特殊的是当只有一个腿时,桌子是稳定的,当有两个腿时两个腿必须都得是最高的,才稳定。

    分析

    这题其实和去年的牛客的一道砍树题一样的(但是我没想起来那题,当时看的题解,稍微改了一下代码,就交了印象不深刻。。。)

    Governing sand

    首先我们按照桌子腿的高度从小到大排序,然后枚举当前最高的高度。

    大于当前高度的肯定都要删除掉,用一个suf后缀来维护。

    我们知道当前高度的桌腿的数量,根据这个数量算出小于这个高度的我们要删除几个?x个

    然后我们用一颗权值线段树维护桌腿的数量以及价值。

    查询前x个最小的权值和,当前高度的花费就是suf[i+1]+query(x)。

    代码

    #include<bits/stdc++.h>
    #define pb push_back
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const int N=1e5+10;
    const int mod=1e9+7;
    const int inf=0x3f3f3f3f;
    const double eps=1e-14;
    
    struct note
    {
        int wei,val;
    }arr[N];
    bool cmp(note a,note b)
    {
        return a.wei<b.wei;
    }
    int suf[N];
    struct tree
    {
        int num,sum;
    }node[N];
    void build(int rt,int l,int r)
    {
        node[rt].num=node[rt].sum=0;
        if(l==r) return ;
        int mid=(l+r)/2;
        build(rt*2,l,mid);
        build(rt*2+1,mid+1,r);
    }
    void pushup(int rt)
    {
        node[rt].num=node[rt*2].num+node[rt*2+1].num;
        node[rt].sum=node[rt*2].sum+node[rt*2+1].sum;
    }
    void update(int rt,int l,int r,int pos)
    {
        if(l==r)
        {
            node[rt].num++;
            node[rt].sum+=l;
            return;
        }
        int mid=(l+r)/2;
        if(pos<=mid) update(rt*2,l,mid,pos);
        else update(rt*2+1,mid+1,r,pos);
        pushup(rt);
    }
    int query(int rt,int l,int r,int k)
    {
        if(l==r) return k*l;
        int lnum=node[rt*2].num;//左子树中桌腿数量
        int mid=(l+r)/2;
        if(k<=lnum) return query(rt*2,l,mid,k);
        else return node[rt*2].sum+query(rt*2+1,mid+1,r,k-lnum);
    }
    int main()
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&arr[i].wei);
        for(int i=1;i<=n;i++)
            scanf("%d",&arr[i].val);
        sort(arr+1,arr+1+n,cmp);//按照高度从小到大排序
        for(int i=n;i;i--)//计算后缀
            suf[i]=suf[i+1]+arr[i].val;
        int now,ans=inf;
        build(1,1,200);
        for(int i=1;i<=n;i++)
        {
            now=0;
            int j=i;
            while(j<=n&&arr[j].wei==arr[i].wei)//计算当前高度的桌腿的数量,下标
            {
                j++;
                now++;
            }
            int x=max(i-now,0);//小于当前高度,要删去的数量
            ans=min(ans,suf[j]+query(1,1,200,x));//计算贡献
            for(int k=i;k<j;k++)//把当前高度更新如线段树
                update(1,1,200,arr[k].val);
            i=j-1;
        }
        printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    有关Backgroundworker
    DataGridView风格设置
    Dev控件GridControl实现CheckBox列和ComBox列
    ALTER PROFILE DEFAULT LIMIT PASS_LIFE_TIME UNLIMITED
    PowerDesigner的Additional Checkes 中使用统配符
    PowerDesigner生成sql脚本时去掉双引号并把字段名设为大写
    PowerDesigner中的域(Domain)的概念及应用
    Oracle Sql中输入特殊字符 转义字符
    机械键盘 按一次字母有时候出来2个
    IE内嵌google chrome frame解决浏览器兼容问题
  • 原文地址:https://www.cnblogs.com/valk3/p/12772180.html
Copyright © 2011-2022 走看看