zoukankan      html  css  js  c++  java
  • CF436F Banners

    Description

    All modern mobile applications are divided into free and paid. Even a single application developers often release two versions: a paid version without ads and a free version with ads.

    Suppose that a paid version of the app costs $ p $ ( $ p $ is an integer) rubles, and the free version of the application contains $ c $ ad banners. Each user can be described by two integers: $ a_{i} $ — the number of rubles this user is willing to pay for the paid version of the application, and $ b_{i} $ — the number of banners he is willing to tolerate in the free version.

    The behavior of each member shall be considered strictly deterministic:

    - if for user $ i $ , value $ b_{i} $ is at least $ c $ , then he uses the free version,
    - otherwise, if value $ a_{i} $ is at least $ p $ , then he buys the paid version without advertising,
    - otherwise the user simply does not use the application.

    Each user of the free version brings the profit of $ c×w $ rubles. Each user of the paid version brings the profit of $ p $ rubles.

    Your task is to help the application developers to select the optimal parameters $ p $ and $ c $ . Namely, knowing all the characteristics of users, for each value of $ c $ from $ 0 $ to $ (max b_{i})+1 $ you need to determine the maximum profit from the application and the corresponding parameter $ p $ .

    Solution

    发现$p$的最优值肯定是某个用户的$a$

    先将所有用户按照$b$排序,那么枚举$c$时就可以单调地将每个用户加入一个数据结构,广告费可以$O(1)$计算,现在只需要考虑软件付费

    设$d_i$表示$p$值为$i$时产生的总收益,那么加入一个用户时会对所有$i < a$的$d$增加一个$i$,相当于区间加等差数列

    可以在值域上分块,对于完整的块更改标记,不完整的块暴力重建

    每次查询的时候对每个块中的最大值求$max$即可

    现在考虑如何找到每个块中的最大值

    设标记为$cnt$,那么当$i < j$且$d_i+i imes cnt < d_j +j imes cnt$,有

    $$frac{d_i - d_j}{j-i} leq cnt$$

    那么在每个块内用队列维护一个下凸壳即可

    #include<algorithm>
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    int n,w,B,blo[100005],q[320][320],h[320],t[320],pos=1,cnt[320],maxa;
    long long d[100005];
    struct Node{
        int a,b;
        bool operator < (const Node &z)const{return b<z.b;}
    }node[100005];
    inline int read(){
        int w=0,f=1;
        char ch=0;
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
        while(ch>='0'&&ch<='9')w=(w<<1)+(w<<3)+ch-'0',ch=getchar();
        return w*f;
    }
    double slope(int x,int y){return 1.0*(d[x]-d[y])/(y-x);}
    void solve(int x){while(h[x]<t[x]&&slope(q[x][h[x]],q[x][h[x]+1])<=cnt[x])++h[x];}
    void insert(int x){
        if(!x)return;
        for(int i=1;i<blo[x];i++)++cnt[i],solve(i);
        int l=(blo[x]-1)*B+1,r=min(blo[x]*B,maxa),id=blo[x];
        for(int i=l;i<=r;i++)d[i]+=1ll*cnt[id]*i;
        for(int i=l;i<=x;i++)d[i]+=i;
        h[id]=1,t[id]=0;
        for(int i=l;i<=r;i++){
            while(h[id]<t[id]&&slope(q[id][t[id]-1],q[id][t[id]])>=slope(q[id][t[id]],i))--t[id];;
            q[id][++t[id]]=i;
        }
        cnt[id]=0,solve(id);
    }
    int main(){
        n=read(),w=read();
        for(int i=1;i<=n;i++)node[i]=(Node){read(),read()},maxa=max(maxa,node[i].a);
        sort(node+1,node+n+1),B=sqrt(maxa);
        for(int i=1;i<=maxa;i++)blo[i]=(i-1)/B+1;
        for(int i=1;i<=blo[maxa];i++)h[i]=t[i]=1,q[i][1]=min(maxa,i*B);
        for(int c=0;c<=node[n].b+1;c++){
            while(pos<=n&&node[pos].b<c)insert(node[pos].a),++pos;
            long long ans1=0,ans2=0;
            for(int i=1;i<=blo[maxa];i++){
                int x=q[i][h[i]];
                if(1ll*cnt[i]*x+d[x]>ans1)ans1=1ll*cnt[i]*x+d[x],ans2=x;
            }
            printf("%I64d %I64d
    ",ans1+1ll*w*c*(n-pos+1),ans2);
        }
        return 0;
    }
    Banners
  • 相关阅读:
    支持向量机SVM知识点概括
    决策树知识点概括
    HDU 3081 Marriage Match II
    HDU 3572 Task Schedule
    HDU 4888 Redraw Beautiful Drawings
    Poj 2728 Desert King
    HDU 3926 Hand in Hand
    HDU 1598 find the most comfortable road
    HDU 4393 Throw nails
    POJ 1486 Sorting Slides
  • 原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/14259118.html
Copyright © 2011-2022 走看看