现在的位置: 首页 > 综合 > 正文

CSU 1097 Gifts with different style

2018年01月15日 ⁄ 综合 ⁄ 共 2002字 ⁄ 字号 评论关闭

1097: Gifts with different style

Time Limit: 1 Sec  Memory Limit: 16 MB
SUBMIT: 139  Solved: 38
[SUBMIT][STATUS]

Description

    前些日子GBQC国的小明在凤凰古城痛痛快快地玩了两天,临走之前希望给女友带回两件不同种类的纪念品,而且小明的背包最多只能容纳总体积不超过V的物品,各个纪念品使其女友的高兴程度的增加值也不全是一样的。

    现在小明想知道,对于小明有有财力购买的N个纪念品,他需要买回哪两个才能使女友的高兴程度的增加值最大呢?

Input

输入包含多组测试数据。

对于每组测试数据,第一行包含三个整数N(1<=N<=10^5), C(1<=C<=10^4), V(1<=V<=10^4),其中N表示小明有财力购买的一共有N个纪念品,C表示市面上销售的纪念品一共可以分为C个种类,V表示小明的背包最多只能容纳体积不超过V的物品。接下来N行,每行用三个正整数i(1<=i<=C)、j(1<=j<=10^4)、k(1<=k<=10^5)描述一个可以购买的纪念品,表示这个纪念品属于第i个种类,其体积为j,如果将其买回可使女友的高兴程度增加k。

Output

对于每组测试数据,用一行输出一个整数表示小明最多可以让女友的高兴程度增加多少。如果小明没办法带回两件不同种类的纪念品,则输出“-1”(不包括引号)。

Sample Input

2 3 51 2 32 4 13 3 51 2 41 2 53 3 2

Sample Output

-17

HINT

    由于数据量较大,推荐使用scanf和printf。

Source

这个题目咋一看,还以为是个分组背包问题(据说分组背包优化一下可以水过),不过正解是线段树

题目的关键之处在于只取2件物品,用线段树保存前k类,在1-v体积下的最大价值。然后计算在前k类和k+1类中各取一个的最大价值。

线段树还是有些不熟0.0

另外原来scanfprintfcincout快很多 Orz.......

我开始还以为是一样的呢,以后尽量用scanfprintf

Num[rt]保存的是在区域类的最大值.

#include<stdio.h>
#include<vector>
using namespace std;
 
#define MAXN 10001
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define max(a,b) a>b?a:b
struct node{
    int w,v;
};
 
int num[MAXN<<2];
 
void build(int l,int r,int rt)
{
    num[rt]=0;
    if(l==r)
        return ;
    int m=(l+r)>>1;
    build(lson);
    build(rson);
}
 
void update(int w,int v,int l,int r,int rt)
{
    num[rt]=max(v,num[rt]);
    if(l==r)
        return ;
    int m=(l+r)>>1;
    if(w<=m)
        update(w,v,lson);
    else
        update(w,v,rson);
}
 
int query(int tmp,int l,int r,int rt)
{
    if(l==r)
        return num[rt];
    int m=(l+r)>>1;
    if(tmp<=m)
        return query(tmp,lson);
    else
        return max(num[rt<<1],query(tmp,rson));
}
 
int main(void)
{
    int N,C,V;
    freopen("d:\\in.txt","r",stdin);
    while(scanf("%d%d%d",&N,&C,&V)==3)
    {
        vector<node>list[10001];
        node tmp;
        int i,j,k;
        for(i=1;i<=N;i++)
        {
            scanf("%d%d%d",&k,&tmp.w,&tmp.v);
            list[k].push_back(tmp);
        }
        build(1,V,1);
        int len,temp;
        int sum=-1;
        for(i=1;i<=C;i++)
        {
            len=list[i].size();
            if(!len)
                continue;
            for(j=0;j<len;j++)            
                if(V-list[i][j].w>0)
                {
                    temp=query(V-list[i][j].w,1,V,1);   //前k类在V-list[i][j].w下的最大值
                    if(temp)
                        sum=max(sum,temp+list[i][j].v);
                }
            for(j=0;j<len;j++)            //更新前k类在各种容量下的最大值
                if(list[i][j].w<=V)
                    update(list[i][j].w,list[i][j].v,1,V,1);
        }
        printf("%d\n",sum);
    }
    return 0;
}

抱歉!评论已关闭.