• dtoi4641 小店购物


    题意:

         有n个商品,每个商品有一个价格和价值。m次操作,每次更改一个商品的信息或者询问一个k,表示一开始有k元钱,然后问会买到价值多少的商品。

         购买方式很特别,分若干轮,每一轮从我能买的物品中选择一个价值最大的(相同的选择价格最小的),然后买下它,重复上述操作,直到买不了任何东西。

         n,m<=100000,其余数值<=1000000000。

    题解:

         如果每次只买一轮,那么问题很简单,使用权值线段树维护商品价值最大值即可。

         那么如果要买很多轮,那对于每一轮,会买到一个商品,这个商品是能买到的价值最大的。

         这意味着什么,意味着下一轮如果有能力购买它,依然会选择它。也就是说,找到一个要买的物品,然后一直买直到钱不够买它为止(这个价值可以直接计算),再进行下一轮购买。

         这样的效率就是m*log*操作的轮数。可以证明,按照这样的方法操作,操作次数不会超过log2(1000000000)。

         证明也很容易,如果这个商品的价格>手里钱数的一半,那减掉他之后钱数至少减半。如果商品价格<手里钱数的一半,那会一直买它直到买不起,那么最后钱数也会<商品价格<原来钱数的一半。所以每次钱数至少减半,那么操作次数就是log次。

         还有个修改操作,由于物品的价格可能会相同,所以在线段树的每一个叶子上面要开一个multiset来记录商品,用于增加和删除。

    #include<cstdio>
    #include<set>
    #include<algorithm>
    #include<cstdlib>
    using namespace std;
    const int INF=1e9;
    int n,m,w[100002],p[100002],cnt=1,Max,cost;
    multiset<int>q[6000002];
    typedef struct{
        int ls,rs,Max,cost;
    }XDS;
    XDS xds[6000002];
    void gengxin(int root,int begin,int end,int wz,int z,bool u){
        if (begin==end)
        {
            if (u)
            {
                q[root].insert(z);multiset<int>::iterator it=q[root].end();it--;
                xds[root].Max=*it;xds[root].cost=begin;
            }
            else
            {
                multiset<int>::iterator it=q[root].find(z);q[root].erase(it);
                if (!q[root].empty())
                {
                    it=q[root].end();it--;
                    xds[root].Max=*it;xds[root].cost=begin;
                }
                else xds[root].Max=xds[root].cost=0;
            }
            return;
        }
        int mid=(begin+end)/2;
        if (wz<=mid)
        {
            if (!xds[root].ls)xds[root].ls=++cnt;
            gengxin(xds[root].ls,begin,mid,wz,z,u);
        }
        else
        {
            if (!xds[root].rs)xds[root].rs=++cnt;
            gengxin(xds[root].rs,mid+1,end,wz,z,u);
        }
        if (xds[xds[root].ls].Max>=xds[xds[root].rs].Max)
        {
            xds[root].Max=xds[xds[root].ls].Max;
            xds[root].cost=xds[xds[root].ls].cost;
        }
        else
        {
            xds[root].Max=xds[xds[root].rs].Max;
            xds[root].cost=xds[xds[root].rs].cost;
        }
    }
    void chaxun(int root,int begin,int end,int begin2,int end2){
        if (begin>end2 || end<begin2)return;
        if (begin>=begin2 && end<=end2)
        {
            if (xds[root].Max>Max)
            {
                Max=xds[root].Max;cost=xds[root].cost;
            }
            return;
        }
        int mid=(begin+end)/2;
        chaxun(xds[root].ls,begin,mid,begin2,end2);chaxun(xds[root].rs,mid+1,end,begin2,end2);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++){scanf("%d%d",&w[i],&p[i]);gengxin(1,1,INF,p[i],w[i],1);}
        for (int i=1;i<=m;i++)
        {
            int op;
            scanf("%d",&op);
            if (op==1)
            {
                int x,ww,pp;
                scanf("%d%d%d",&x,&ww,&pp);
                gengxin(1,1,INF,p[x],w[x],0);
                p[x]=pp;w[x]=ww;
                gengxin(1,1,INF,p[x],w[x],1);
            }
            else
            {
                int k;long long ans=0;
                scanf("%d",&k);
                while(1)
                {
                    Max=0;cost=0;chaxun(1,1,INF,1,k);
                    if (Max)
                    {
                        ans+=(long long)k/cost*Max;
                        k=k-k/cost*cost;
                    }
                    else break;
                }
                printf("%lld
    ",ans);
            }
        }
        return 0;
    }
  • 相关阅读:
    Apache Shiro 的三大核心组件
    MyBatis 与 Hibernate 有哪些不同?
    #{}和${}的区别是什么?
    Java Web中前端提交的表单两种方式(处理中文乱码问题)
    Http中200、302、304、404和500等响应状态码所表示的意义?
    jsp三大指令标记,七大动作标记、详解。
    session 的工作原理
    JSP的四种作用域
    jsp有哪些内置对象?作用分别是什么?
    什么是session?什么是cookie?session和cookie有什么区别?
  • 原文地址:https://www.cnblogs.com/1124828077ccj/p/12286656.html
Copyright © 2020-2023  润新知