hdu 4791 長沙現場賽A題

題意:打印紙張,隨着張數的增加,價格非遞增,給出m個詢問打印的張數,求最小的花費。

思路:找到張數所在的區間,最大的花費就是該區間的價格*張數,如果要打印多餘的張數,就在後面的區間找,因爲後邊的區間都是張數大於目標張數,所以去區間的最小值,應爲價格是非遞增的,張數是遞增的,所以要找區間的張數*價格的最小值,用線段樹就可以。。。

寫完了,纔想到其實沒這麼複雜,可以直接從後往前求每個區間右邊的最小值,記錄一下,直接用就可以了。


#include<stdio.h>
#include<string.h>
const int N=100100;
__int64 cnt[N],num[N];
int n;
struct Tree
{
    int L,R;
    __int64 mw;
}T[N*4];
__int64 min(__int64 a,__int64 b)
{
    if(a>b)return b;
    return a;
}
void buildTree(int L,int R,int id)
{
    T[id].L=L;T[id].R=R;
    if(L==R)
    {
        T[id].mw=cnt[L]*num[L];
        return ;
    }
    int li,ri,mid;
    mid=(L+R)>>1;
    li=id<<1;ri=li|1;
    buildTree(L,mid,li);
    buildTree(mid+1,R,ri);
    T[id].mw=min(T[li].mw,T[ri].mw);
}
__int64 find(int L,int R,int id)
{
    if(T[id].L==L&&T[id].R==R)
        return T[id].mw;
    int li=id<<1,ri=li|1,mid=(T[id].L+T[id].R)>>1;
    if(R<=mid)return find(L,R,li);
    else if(L>mid) return find(L,R,ri);
    else return min(find(L,mid,li),find(mid+1,R,ri));
}
int findnum(__int64 w)
{
    int L,R,mid,flag;
    L=1;R=n;flag=1;
    while(L<=R)
    {
        mid=(L+R)>>1;
        if(num[mid]<=w)
        {
            flag=mid;
            L=mid+1;
        }
        else R=mid-1;
    }
    return flag;
}
int main()
{
    int i,j,m,t;
    __int64 sum,w;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;i++)
            scanf("%I64d%I64d",&num[i],&cnt[i]);
        buildTree(1,n,1);
        while(m--)
        {
            scanf("%I64d",&w);
            j=findnum(w);
            if(j==n){printf("%I64d\n",cnt[j]*w);continue;}
            sum=find(j+1,n,1);
            printf("%I64d\n",min(sum,cnt[j]*w));
        }
    }
    return 0;
}




#include<stdio.h>
#include<string.h>
const int N=100005;
__int64 cnt[N],num[N],minw[N];
int n;
__int64 min(__int64 a,__int64 b)
{
    if(a>b)return b;
    return a;
}
int findnum(__int64 w)
{
    int L,R,mid,flag;
    L=1;R=n;flag=1;
    while(L<=R)
    {
        mid=(L+R)>>1;
        if(num[mid]<=w)
        {
            flag=mid;
            L=mid+1;
        }
        else R=mid-1;
    }
    return flag;
}
int main()
{
    int i,j,m,t;
    __int64 w;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;i++)
            scanf("%I64d%I64d",&num[i],&cnt[i]);
        minw[n]=num[n]*cnt[n];
        for(i=n;i>=2;i--)
        {
            minw[i-1]=minw[i];
            if(num[i]*cnt[i]<minw[i])
                minw[i-1]=num[i]*cnt[i];
        }
        while(m--)
        {
            scanf("%I64d",&w);
            j=findnum(w);
            if(j==n){printf("%I64d\n",cnt[j]*w);continue;}
            printf("%I64d\n",min(cnt[j]*w,minw[j+1]));
        }
    }
    return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章