题目链接:http://codeforces.com/contest/799/problem/C点击打开链接
一开始用很复杂的思路写了好久 大致就是利用优先队列排序 创立另一个结构体记录每个数量下的金币和钻石能够获得的最大价值 然后遍历每个喷泉与最大金币减去当前喷泉的价值 取最大 注意可能出现重复取的情况 还需判断 比较繁琐
之后学习树状数组 简便许多
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include<algorithm>
#include <math.h>
#include <string.h>
#include <limits.h>
#include <string>
#include <queue>
#include <stack>
using namespace std;
struct xjy
{
int val;
int cost;
char c;
bool operator < (const xjy &r)
const{
if(cost==r.cost)
return val>r.val;
return cost>r.cost;
}
}xjyc[100001],xjyd[100001];
struct va
{
int val1;
int val2;
int valcost;
}vac[100001],vad[100001];
priority_queue<xjy> qc,qd,qcc,qdd;
int main()
{
int n,coins,dia;
scanf("%d%d%d",&n,&coins,&dia);
for(int i=0;i<n;i++)
{
struct xjy mid;
scanf("%d%d %c",&mid.val,&mid.cost,&mid.c);
if(mid.c=='C')
{
if(mid.cost<=coins)
{
qc.push(mid);
qcc.push(mid);
}
}
else if(mid.c=='D')
{
if(mid.cost<=dia)
{
qd.push(mid);
qdd.push(mid);
}
}
}
int cmax1=0,cmax2=0,dmax1=0,dmax2=0,ccost=0,dcost=0;
for(int i=0;i<=coins;i++)
{
if(!qc.empty())
{
while(i==qc.top().cost&&!qc.empty())
{
if(cmax1<=qc.top().val)
{
cmax2=cmax1;
cmax1=max(cmax1,qc.top().val);
ccost=qc.top().cost;
}
qc.pop();
}
vac[i].val1=cmax1;
vac[i].val2=cmax2;
vac[i].valcost=ccost;
}
else
{
vac[i].val1=cmax1;
vac[i].val2=cmax2;
vac[i].valcost=ccost;
}
}
for(int i=0;i<=dia;i++)
{
if(!qd.empty())
{
while(i==qd.top().cost&&!qd.empty())
{
if(dmax1<=qd.top().val)
{
dmax2=dmax1;
dmax1=max(dmax1,qd.top().val);
dcost=qd.top().cost;
}
qd.pop();
}
vad[i].val1=dmax1;
vad[i].val2=dmax2;
vad[i].valcost=dcost;
}
else
{
vad[i].val1=dmax1;
vad[i].val2=dmax2;
vad[i].valcost=dcost;
}
}
int sum1=0;
while(!qcc.empty())
{
xjy mid=qcc.top();
qcc.pop();
if(mid.val==vac[coins-mid.cost].val1&&mid.cost==vac[coins-mid.cost].valcost)
{
int summid=mid.val+vac[coins-mid.cost].val2;
if(vac[coins-mid.cost].val2==0)
summid=0;
sum1=max(sum1,summid);
}
else
{
int summid=mid.val+vac[coins-mid.cost].val1;
sum1=max(sum1,summid);
}
}
int sum2=0;
while(!qdd.empty())
{
xjy mid=qdd.top();
qdd.pop();
if(mid.val==vad[dia-mid.cost].val1&&mid.cost==vad[dia-mid.cost].valcost)
{
int summid=mid.val+vad[dia-mid.cost].val2;
if(vad[dia-mid.cost].val2==0)
summid=0;
sum2=max(sum2,summid);
}
else
{
int summid=mid.val+vad[dia-mid.cost].val1;
if(vad[dia-mid.cost].val2==0)
summid=0;
sum2=max(sum2,summid);
}
}
int sum3=vac[coins].val1+vad[dia].val1;
if(vac[coins].val1==0||vad[dia].val1==0)
sum3=0;
int sum=max(sum1,sum2);
sum=max(sum,sum3);
printf("%d\n",sum);
}
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include<algorithm>
#include <math.h>
#include <string.h>
#include <limits.h>
#include <string>
#include <queue>
#include <stack>
using namespace std;
int coins[111111],dia[111111];
int maxn(int *tree,int k)
{
int maxn=0;
while(k>0)
{
maxn=max(maxn,tree[k]);
k-=k&-k;
}
return maxn;
}
void add(int *tree,int k,int num)
{
while(k<=100000)
{
tree[k]=max(tree[k],num);
k+=k&-k;
}
}
int main()
{
int n,c,d;int mmax=0;int ans=0;;
scanf("%d%d%d",&n,&c,&d);
for(int i=0;i<n;i++)
{
int val,cost;char cchar;
scanf("%d%d %c",&val,&cost,&cchar);
if(cchar=='C')
{
mmax=maxn(dia,d);
if(cost>c)
continue;
mmax=max(mmax,maxn(coins,c-cost));
add(coins,cost,val);
}
else
{
mmax=maxn(coins,c);
if(cost>d)
continue;
mmax=max(mmax,maxn(dia,d-cost));
add(dia,cost,val);
}
if(mmax)
ans=max(ans,mmax+val);
}
printf("%d",ans);
}
这次线段树写了一遍 更新下吧
线段树与树状数组类似 先查询后更新 这样保证了不会重复取同一个物品 也不会漏掉情况(因为每对物品会有两次取到的情况)
#include <bits/stdc++.h>
using namespace std;
#define maxn 100010
struct xjy
{
int left ;
int right;
int sum;
};
xjy tree[maxn<<2];
struct node
{
int val;
int cost;
bool operator < (const node &r)const
{
return cost<r.cost;
}
};
vector<node> c,d;
void build(int i,int left,int right)
{
if(left==right)
{
tree[i].left=left;
tree[i].right=right;
tree[i].sum=-1;
return;
}
int mid=(left+right)>>1;
build (i<<1,left,mid);
build(i<<1|1,mid+1,right);
tree[i].left=left;
tree[i].right=right;
tree[i].sum=-1;
}
void update(int i,int pos,int val)
{
if(tree[i].left==pos&&tree[i].right==pos)
{
tree[i].sum=max(tree[i].sum,val);//这里可能有相同价格的 因此是比较而不是等于
return ;
}
int mid=(tree[i].left+tree[i].right)>>1;
if(pos<=mid)
update(i<<1,pos,val);
else
update(i<<1|1,pos,val);
tree[i].sum=max(tree[i<<1].sum,tree[i<<1|1].sum);
}
int aans=0;
void query(int i,int left,int right)
{
if(tree[i].left==left&&tree[i].right==right)
{
aans=max(aans,tree[i].sum);
return ;
}
int mid =(tree[i].left+tree[i].right)>>1;
if(right<=mid)
query(i<<1,left,right);
else if(left>mid)
query(i<<1|1,left,right);
else
{
query(i<<1,left,mid);
query(i<<1|1,mid+1,right);
}
}
int main()
{
int n,coins,dia;
int ans=-1;
int cans=-1,dans=-1;
scanf("%d%d%d",&n,&coins,&dia);
for(int i=1;i<=n;i++)
{
int val,cost;char cc;
scanf("%d%d %c",&val,&cost,&cc);
if(cc=='C')
{
node mid;
mid.val=val;
mid.cost=cost;
c.push_back(mid);
if(coins>=cost)
cans=max(cans,val);
}
else
{
node mid;
mid.val=val;
mid.cost=cost;
d.push_back(mid);
if(dia>=cost)
dans=max(dans,val);
}
}
if(cans!=-1&&dans!=-1)
ans=cans+dans;
build(1,1,coins);
for(int i=0;i<c.size();i++)
{
if(coins>c[i].cost)
{
aans=-1;
query(1,1,coins-c[i].cost);
if(aans>0)
ans=max(ans,c[i].val+aans);
update(1,c[i].cost,c[i].val);
}
}
build(1,1,dia);
for(int i=0;i<d.size();i++)
{
if(dia>d[i].cost)
{
aans=-1;
query(1,1,dia-d[i].cost);
if(aans>0)
ans=max(ans,d[i].val+aans);
update(1,d[i].cost,d[i].val);
}
}
if(ans==-1)
printf("0");
else
printf("%d",ans);
}