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;
}

 

posted @ 2019-07-30 14:38  eason99  阅读(119)  评论(0编辑  收藏  举报