• C. Playlist(权值线段树查询前k大和)


    https://codeforces.com/contest/1140/problem/C

    #include<bits/stdc++.h>
    using namespace std;
    #define ls rt<<1
    #define rs (rt<<1)+1
    typedef long long ll;
    #define fuck(x) cout<<#x<<"     "<<x<<endl;
    const int maxn=3e5+10;
    const int maxnn=1e6+10;
    int d[4][2]={1,0,-1,0,0,1,0,-1};
    
    struct node
    {
        int a,b;
        friend bool operator< (const node&mm,const node&nn)
        {
            return mm.b<nn.b;
        }
    }song[maxn];
    int num[maxnn*5];
    ll sum[maxnn*5];
    ll query(int rt,int L,int R,int k){
    
        if(num[rt]<=k)
            return sum[rt];
        if(L==R) return k*L;     //到叶子的时候要注意处理,不然会继续向下搜会re
        int mid=(L+R)>>1;
        ll tmp=0;
        if(num[2*rt+1]>=k)
            tmp=query(2*rt+1,mid+1,R,k);
        else
        {
            tmp=sum[rs];
            tmp+=query(2*rt,L,mid,k-num[2*rt+1]);
        }
        return tmp;
    }
    void update(int rt,int L,int R,int pos)
    {
        if(L==R) {
            num[rt]++,sum[rt]+=pos;
            return ;
        }
        int mid=(L+R)>>1;
        if(pos<=mid)
            update(2*rt,L,mid,pos);
        else
            update(2*rt+1,mid+1,R,pos);
        num[rt]=num[2*rt]+num[2*rt+1];
        sum[rt]=sum[2*rt]+sum[2*rt+1];
    }
    int main(){
        int n,k;
        ll maxx=-1,tmp;
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++) scanf("%d%d",&(song[i].a),&(song[i].b));
        sort(song+1,song+n+1);
        for(int i=n;i>=1;i--)
        {
            tmp=1LL*song[i].b*(query(1,1,1e6,min(k-1,n-i))+song[i].a);
            maxx=max(maxx,tmp);
            update(1,1,1e6,song[i].a);
        }
        cout<<maxx<<endl;
        return 0;
    }
  • 相关阅读:
    大三进度条01
    阅读笔记01
    问题账户需求分析
    《人月神话》阅读笔记02
    《人月神话》阅读笔记01
    每周总结(第五周)
    《构建之法》阅读笔记06
    《构建之法》阅读笔记05
    《构建之法》阅读笔记04
    《构建之法》阅读笔记03
  • 原文地址:https://www.cnblogs.com/eason9906/p/11754733.html
Copyright © 2020-2023  润新知