ZOJ 3726 Alice's Print Service 二分+rmq

来源:互联网 发布:java extends super 编辑:程序博客网 时间:2024/04/29 06:32

        打印k页的资料,给出n中付费方案,一次打印超过s1但不超过s2的每页收费p1,超过s2不超过s3的收费p2.....数据保证0=s1<s2<...<sn,p1>=p1>=p3>=...>=pn。接下来m个查询,对于每个查询问最少花多少钱?例如s1=0 s2=100  p1=20 p2=10 的时候,若要打印99页,显然直接打印100页要更便宜一点..所以结果是1000..

        由于数据该要求的都要求了,对于每个查询q,二分找到最大的si使q>=si,这样最少的费用要么是q*si,要么是sj*pj(i<j<=n),由于后面的sj*pj是确定的,要解决的就只是一个区间最小值的问题了..RMQ,线段树之类的随便搞一下就行了,当然也可以提前预处理一下,二分出si后可以O(1)直接出结果....我这写了一个单点更新区间查询的线段树.....

       

#include <iostream>#include <cstdio>#include <algorithm>#include <memory.h>#include <stack>#include <queue>#include <cstring>#define lson id<<1,l,m#define rson id<<1|1,m+1,rusing namespace std;typedef long long ll;const ll inf=(1LL<<60);int n,m;int tt;struct node{    ll s;    ll p;    ll b;    bool operator<(const node &tp)const    {        return b<tp.b;    }}a[120000];struct SGT{    ll dt[480000];   void pushup(int id)   {       dt[id]=min(dt[id<<1],dt[id<<1|1]);   }   void build(int id,int l,int r)   {       if (l==r)       {           dt[id]=(1LL<<62);           return ;       }       int m=(l+r)>>1;       build(lson);       build(rson);       pushup(id);   }   void modify(int id,int l,int r,int pos,ll c)   {       if (l==r)       {           dt[id]=c;           return;       }       int m=(l+r)>>1;       if (pos<=m) modify(lson,pos,c);       else modify(rson,pos,c);       pushup(id);   }   ll query(int id,int l,int r,int L,int R)   {       if (l==L && r==R)       {           return dt[id];       }       int m=(l+r)>>1;       ll res=inf;       if (R<=m) res=query(lson,L,R);       else if (L>m) res=query(rson,L,R);       else res=min(query(lson,L,m),query(rson,m+1,R));       return res;   }}sgt;int main(){//    freopen("in.txt","r",stdin);    scanf("%d",&tt);    while(tt--)    {        scanf("%d%d",&n,&m);        for (int i=1; i<=n; i++)        {            scanf("%lld%lld",&a[i].s,&a[i].p);            a[i].b=(ll)(a[i].s*(ll)a[i].p);        }        sgt.build(1,1,n);        for (int i=1; i<=n; i++)        {            sgt.modify(1,1,n,i,a[i].b);        }        ll tmp;        ll ans=0;        for (int i=1; i<=m; i++)        {            scanf("%lld",&tmp);            int l=1,r=n+1;            int mid;            if (l!=r)            {                while (l<r)                {                    mid=(l+r)>>1;                    if (a[mid].s>tmp)  r=mid;                    else l=mid+1;                }                ans=tmp*a[l-1].p;                if (l<=n) ans=min(ans,sgt.query(1,1,n,l,n));            }            else ans=tmp*a[l].p;            printf("%lld\n",ans);        }    }    return 0;}


原创粉丝点击