这题的树状数组是用来维护区间最大值的!非常神奇
第一次见到这种用法,其实和区间求和也没什么差别
/* 树状数组魔改版 有三种方案:选两种c,选两个d,选一个c一个d 前两种方案需要选出符合条件的魅力值最大的物品,枚举的话复杂度n*n, 那么将每件物品按照价格升序排序,同价格时按照魅力值降序排序 枚举每件物品,然后第二件物品就是剩下的钱可以买的魅力值最大的物品 */ #include<bits/stdc++.h> using namespace std; #define ll long long #define maxn 100005 struct C{int p,b;}c[maxn]; struct D{int p,b;}d[maxn]; int ans,n,C,D,p,b,totc,totd; char s[10]; int bit[maxn]; void update(int x,int val){ while(x<=maxn-2){ bit[x]=max(val,bit[x]); x+=x&-x; } } int query(int x){ int res=0; while(x){ res=max(res,bit[x]); x-=x&-x; } return res; } int main(){ totc=totd=ans=0; scanf("%d%d%d",&n,&C,&D); for(int i=1;i<=n;i++){ scanf("%d%d%s",&b,&p,s); if(s[0]=='C' && p<=C)c[++totc].p=p,c[totc].b=b; else if(s[0]=='D' && p<=D)d[++totd].p=p,d[totd].b=b; } int max1=-1,max2=-1; for(int i=1;i<=totc;i++)max1=max(max1,c[i].b); for(int i=1;i<=totd;i++)max2=max(max2,d[i].b); if(max1+1 && max2+1) ans=max(ans,max1+max2); memset(bit,0,sizeof bit); for(int i=1;i<=totc;i++){ int tmp=query(C-c[i].p); if(tmp>0) ans=max(ans,c[i].b+tmp); update(c[i].p,c[i].b); } memset(bit,0,sizeof bit); for(int i=1;i<=totd;i++){ int tmp=query(D-d[i].p); if(tmp>0) ans=max(ans,d[i].b+tmp); update(d[i].p,d[i].b); } printf("%d ",ans); }