*【CodeForces - 799C】Fountains (线段树 或 树状数组)

版权声明:欢迎学习我的博客,希望ACM的发展越来越好~ https://blog.csdn.net/qq_41289920/article/details/82533062

题干:

Arkady plays Gardenscapes a lot. Arkady wants to build two new fountains. There are n available fountains, for each fountain its beauty and cost are known. There are two types of money in the game: coins and diamonds, so each fountain cost can be either in coins or diamonds. No money changes between the types are allowed.

Help Arkady to find two fountains with maximum total beauty so that he can buy both at the same time.

Input

The first line contains three integers nc and d (2 ≤ n ≤ 100 000, 0 ≤ c, d ≤ 100 000) — the number of fountains, the number of coins and diamonds Arkady has.

The next n lines describe fountains. Each of these lines contain two integers bi and pi (1 ≤ bi, pi ≤ 100 000) — the beauty and the cost of the i-th fountain, and then a letter "C" or "D", describing in which type of money is the cost of fountain i: in coins or in diamonds, respectively.

Output

Print the maximum total beauty of exactly two fountains Arkady can build. If he can't build two fountains, print 0.

Examples

Input

3 7 6
10 8 C
4 3 C
5 6 D

Output

9

Input

2 4 5
2 5 C
2 1 D

Output

0

Input

3 10 10
5 5 C
5 5 C
10 11 D

Output

10

Note

In the first example Arkady should build the second fountain with beauty 4, which costs 3 coins. The first fountain he can't build because he don't have enough coins. Also Arkady should build the third fountain with beauty 5 which costs 6 diamonds. Thus the total beauty of built fountains is 9.

In the second example there are two fountains, but Arkady can't build both of them, because he needs 5 coins for the first fountain, and Arkady has only 4 coins.

题目大意:

解题报告:

   比赛的时候让这个线段树搞垮我了,,很多特殊情况要考虑,并且,最后卡住我的不是线段树那一块,而是之前的C和D两种货币各选一个的那种情况,我是直接,找到就break,但是其实应该是维护一个最大值。。。因为你直接break的话只能保证cost是可符合的最大的,而保证不了val的最大性!我们需要的是val!(%%%WJH大佬)

AC代码1:

#include<bits/stdc++.h>
using namespace std;
const int MAX = 100000 +5;
int n,c,d,totc,totd;
int cc[MAX];
int dd[MAX];
struct Node{
	int val,cost;
	Node(){}
	Node(int val,int cost):val(val),cost(cost){} 
} C[MAX],D[MAX];
struct TREE {
	int l,r;
	int val;
} tree[MAX*4]; 
bool cmp(const Node &a,const Node &b) {
	return a.cost < b.cost;
}
void pushup(int cur) {
	tree[cur].val = max(tree[cur*2].val,tree[cur*2+1].val);
}
void buildc(int l,int r,int cur) {
	tree[cur].l=l;
	tree[cur].r=r;
	if(l == r) {
		tree[cur].val = C[l].val;
		return ;
	}
	int m = (l +r)/2;
	buildc(l,m,cur*2);
	buildc(m+1,r,cur*2+1);
	pushup(cur);
}
void buildd(int l,int r,int cur) {
	tree[cur].l=l;
	tree[cur].r=r;
	if(l == r) {
		tree[cur].val = D[l].val;
		return ;
	}
	int m = (l +r)/2;
	buildd(l,m,cur*2);
	buildd(m+1,r,cur*2+1);
	pushup(cur);
}
int query(int pl,int pr,int cur) {
	if(pl <= tree[cur].l && pr >= tree[cur].r) return tree[cur].val;
	int res = 0;
	if(pl <= tree[cur*2].r) res = query(pl,pr,cur*2);
	if(pr >= tree[cur*2+1].l) res = max(res,query(pl,pr,cur*2+1));
	return res;
}
void update(int tar,int val,int cur) {
	if(tree[cur].l == tree[cur].r) {
		tree[cur].val = val;return ;
	}
	int m = (tree[cur].l + tree[cur].r)/2;
	if(tar <= m) update(tar,val,cur*2);
	else update(tar,val,cur*2+1);
	pushup(cur);
}
signed main()
{
	char op[10];
	int val,cost,flag1=0,flag2=0;
	cin>>n>>c>>d;
	for(int i = 1; i<=n; i++) {
		scanf("%d%d%s",&val,&cost,op);
		if(op[0] == 'C') {
			C[++totc] = Node(val,cost);
		}
		else {
			D[++totd] = Node(val,cost);
		}
	}
	sort(C+1,C+totc+1,cmp);	
	sort(D+1,D+totd+1,cmp);
	int maxx=0,tmp1 = 0,tmp2 = 0,pos;
	for(int i = totc; i>=1; i--) {
		if(C[i].cost <= c) {
			flag1=1;tmp1 = max(tmp1,C[i].val);
		}
	}
	for(int i = totd; i>=1; i--) {
		if(D[i].cost <= d) {
			flag2=1;tmp2 = max(tmp2,D[i].val);
		}
	}
	if(flag1==0 && flag2 == 0) {
		printf("0\n");return 0;
	} 
	if(flag1 == 1 && flag2 == 1) {
		maxx = tmp1 + tmp2;
	}
	if(totc == 1 && totd == 1) {
		if(C[1].cost > c || D[1].cost > d) {
			printf("0\n");return 0;
		}
	}
	for(int i = 1; i<=totc; i++) cc[i] = C[i].cost;
	for(int i = 1; i<=totd; i++) dd[i] = D[i].cost;	
//	printf("maxx = %d\n",maxx);
	//处理C
	if(totc != 0 ) {
		buildc(1,totc,1);
		for(int i =1; i<=totc; i++) {
			if(c-cc[i] < 0) break; 
			update(i,0,1);
			pos = upper_bound(cc+1,cc+totc + 1,c-cc[i]) - cc-1;
			if(pos == 0) continue;
			maxx = max(maxx,C[i].val + query(1,pos,1));
			update(i,C[i].val,1);
		}
	}
	for(int i = 1; i<=MAX; i++) update(i,0,1);
//	printf("%d  %d\n",query(1,1,1),query(1,2,1));
	
	if(totd !=0) {
		buildd(1,totd,1);
		for(int i =1; i<=totd; i++) {
			if(d-dd[i] < 0) break;
			update(i,0,1);
			pos = upper_bound(dd+1,dd+totd + 1,d-dd[i])- dd -1;
			if(pos == 0) continue;
	//		if(dd[pos] > d-dd[i]) pos--;
			maxx = max(maxx,D[i].val + query(1,pos,1));
			update(i,D[i].val,1);
		}
	}
	printf("%d\n",maxx);
	return 0 ;
}
//6 4 9
//6 6 D
//1 4 D
//6 7 C
//7 6 D
//5 7 D
//2 5 D


//6 68 40
//1 18 D
//6 16 D
//11 16 D
//7 23 D
//16 30 D
//2 20 D

//3 9 5
//10 7 C
//8 6 C
//5 3 C

AC代码2:(o(n^2))

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAX = 1e5 + 5 ;
int n,c,d,ans;
struct Node {
	int cost,val;
	char op[5];
} node[MAX];
bool cmp(const Node & a,const Node & b) {
	if(a.val != b.val) return a.val > b.val;
	return a.cost < b.cost;
}
int main()
{
	cin>>n>>c>>d;
	for(int i = 1; i<=n; i++) {
		scanf("%d%d%s",&node[i].val,&node[i].cost,node[i].op);
	}
	sort(node+1,node+n+1,cmp);
	int cc,dd,flag,tmp;
	for(int i = 1; i<=n; i++) {
		cc = c;dd = d;flag = 0 ;
		if(node[i].op[0] == 'C' && node[i].cost <= c) {
			flag=1;cc-=node[i].cost;tmp=node[i].val;
		}
		else if(node[i].op[0] == 'D' && node[i].cost <= d) {
			flag=1;dd-=node[i].cost;tmp = node[i].val;
		}
		if(flag == 0) continue;
		for(int j = i+1; j<=n; j++) {
			if(node[j].op[0] == 'C' && node[j].cost <= cc) {
				ans = max(ans,tmp+node[j].val);break;
			}
			else if(node[j].op[0] == 'D' && node[j].cost <= dd) {
				ans = max(ans,tmp+node[j].val);break;
			}
		}
	}
	printf("%d\n",ans);
	
	return 0 ;
}

AC代码3:(树状数组)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
 
using namespace std;
 
const int maxn = 100000;
 
int C[maxn+10],D[maxn+10];
 
void add(int *tree,int k,int num)
{
	while(k<=maxn)
	{
		tree[k] = max(tree[k],num);
		k+=k&-k;
	}
}
 
int read(int *tree,int k)
{
	int res=0;
	while(k)
	{
		res = max(res,tree[k]);
		k-=k&-k;
	}
	return res;
}
 
int main(void)
{
    int n,c,d,i,j;
    while(scanf("%d%d%d",&n,&c,&d)==3)
    {
        memset(C,0,sizeof(C));
        memset(D,0,sizeof(D));
        int ans = 0;
        for(i=1;i<=n;i++)
        {
            int b,p;
            char t[5];
            scanf("%d%d%s",&b,&p,t);
            int maxn;
            if(t[0] == 'C')
            {
                maxn = read(D,d);
                if(p > c)
                    continue;
                maxn = max(maxn,read(C,c-p));
                add(C,p,b);
            }
            else
            {
                maxn = read(C,c);
                if(p > d)
                    continue;
                maxn = max(maxn,read(D,d-p));
                add(D,p,b);
            }
            if(maxn)
                ans = max(ans,maxn + b);
        }
        cout << ans << endl;
    }
 
    return 0;
}

AC代码4:(tourist)

#include <bits/stdc++.h>

using namespace std;

const int N = 1234567;

int pref[N], a[N], b[N];
char c[N];

int solve(vector < pair <int, int> > z, int b) {
	sort(z.begin(), z.end());
	int cnt = z.size();
	if (cnt < 2) {
		return 0;
	}
	pref[0] = 0;
	for (int i = 0; i < cnt; i++) {
		pref[i + 1] = max(pref[i], z[i].second);
	}
	int i = 0;
	int res = 0;
	for (int j = cnt - 1; j >= 0; j--) {
		while (i < j && z[i].first + z[j].first <= b) {
			i++;
		}
		i = min(i, j);
		if (i > 0) {
			res = max(res, pref[i] + z[j].second);
		}
	}
	return res;
}

int main() {
	int n, C, D;
	scanf("%d %d %d", &n, &C, &D);
	for (int i = 0; i < n; i++) {
		scanf("%d %d", a + i, b + i);
		c[i] = getchar();
		while (c[i] != 'C' && c[i] != 'D') {
			c[i] = getchar();
		}
	}
	int ans = 0;
	{
		int x = 0, y = 0;
		for (int i = 0; i < n; i++) {
			if (c[i] == 'C' && b[i] <= C) {
				x = max(x, a[i]);
			}
		}
		for (int i = 0; i < n; i++) {
			if (c[i] == 'D' && b[i] <= D) {
				y = max(y, a[i]);
			}
		}
		if (x > 0 && y > 0) {
			ans = max(ans, x + y);
		}
	}
	{
		vector < pair <int, int> > z;
		for (int i = 0; i < n; i++) {
			if (c[i] == 'C') {
				z.push_back(make_pair(b[i], a[i]));
			}
		}
		ans = max(ans, solve(z, C));
	}
	{
		vector < pair <int, int> > z;
		for (int i = 0; i < n; i++) {
			if (c[i] == 'D') {
				z.push_back(make_pair(b[i], a[i]));
			}
		}
		ans = max(ans, solve(z, D));
	}
	printf("%d\n", ans);
	return 0;
}

AC代码5:(在线搞,以cost建树(而不是排好序后用下标建树),维护最大值)

#include<cstdio>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
const int maxn = 100010;
int a[maxn],acost[maxn],b[maxn],bcost[maxn];
struct node
{
	int Max;
	int l,r;
}t[maxn*4];
void build(int root,int l,int r)
{
	t[root].l=l;
	t[root].r=r;//
	t[root].Max=-1;
	if(l==r)
		return;
	int mid=(l+r)>>1;
	build(2*root,l,mid);
	build(2*root+1,mid+1,r);
}
void update(int root,int index,int val)
{
	int l=t[root].l,r=t[root].r;
	if(l==r)
	{
		t[root].Max=max(t[root].Max,val);
		return;//
	}
	int mid=(l+r)>>1;
	if(index<=mid)
	update(2*root,index,val);
	else
	update(2*root+1,index,val);
	t[root].Max=max(t[root*2].Max,t[root*2+1].Max);
}
int query(int root,int ql,int qr)
{
	int l=t[root].l;
	int r=t[root].r;
 
	if(l==ql&&r==qr)
	{
		return t[root].Max;
	}
	int mid=(l+r)>>1;
	if(qr<=mid)
	return query(2*root,ql,qr);
	else if(ql>mid)
	return query(2*root+1,ql,qr);
	else
	return max(query(2*root,ql,mid),query(2*root+1,mid+1,qr));//2*root+1
}
int main()
{
	int N,C,D;
	while(~scanf("%d%d%d",&N,&C,&D))
	{
		int acnt=0,bcnt=0;
		char ch;
		int c,w;
		int Maxc=-1;
		for(int i=0;i<N;i++)
		{
			scanf("%d%d %c",&c,&w,&ch);
			if(ch=='C')
			{
				a[acnt]=c;acost[acnt++]=w;
			}
			else if(ch=='D')
			{
				b[bcnt]=c;bcost[bcnt++]=w;
			}
			Maxc=max(w,Maxc);
		}
		int ans=-1;
		int res1=-1,res2=-1;
		for(int i=0;i<acnt;i++)
		{
			if(C>=acost[i])
			res1=max(res1,a[i]);
		}
		for(int i=0;i<bcnt;i++)
		{
			if(D>=bcost[i])
			res2=max(res2,b[i]);
		}
		if(res1!=-1&&res2!=-1)ans=res1+res2;
		
		Maxc=max(Maxc,max(C,D));
		build(1,1,Maxc+10);
		for(int i=0;i<acnt;i++)
		{
			int res=-1;
			if(C>acost[i])
			res=query(1,1,C-acost[i]);
			update(1,acost[i],a[i]);
			if(res!=-1)
			ans=max(ans,a[i]+res);
		}
		build(1,1,Maxc);
		for(int i=0;i<bcnt;i++)
		{
			int res=-1;
			if(D>bcost[i])
			res=query(1,1,D-bcost[i]);
			update(1,bcost[i],b[i]);
			if(res!=-1)
			ans=max(ans,b[i]+res);
		}
		if(ans!=-1)
		printf("%d\n",ans);
		else
		printf("0\n");
	}
}

AC代码6:(维护最大价值和次大价值 + 前缀和)(感觉这个题解有问题?)

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define fi  first
#define se  second
#define PII  pair<ll , ll >
typedef long long ll;
const int N = 100005;

int n;
ll  C, D;
PII  c[N], d[N];
ll ans1[N][2], ans2[N][2];
int  cnt1=0, cnt2=0;
//init函数中均可加等号
void Init()
{
    sort(c+1, c+1+cnt1);
    sort(d+1, d+1+cnt2);
    ll mx1=0, mx2=0;
    rep(i,1,cnt1)
    {
        if(mx1 < c[i].se)
        {
            mx2=mx1,  mx1=c[i].se;
            ans1[c[i].fi][0]=mx1;
            ans1[c[i].fi][1]=mx2;
        }
        else if(mx2 < c[i].se)
        {
            mx2=c[i].se;
            ans1[c[i].fi][0]=mx1;//可注释
            ans1[c[i].fi][1]=mx2;
        }

    }
    mx1=0, mx2=0;
    rep(i,1,cnt2)
    {
        if(mx1 < d[i].se)
        {
            mx2=mx1,  mx1=d[i].se;
            ans2[d[i].fi][0]=mx1;
            ans2[d[i].fi][1]=mx2;
        }
        else if(mx2 < d[i].se)
        {
            mx2=d[i].se;
            ans2[d[i].fi][0]=mx1;//可注释
            ans2[d[i].fi][1]=mx2;
        }
    }
    rep(i,1,max(C,D)) rep(j,0,1)
    {
        ans1[i][j]=max(ans1[i][j], ans1[i-1][j]);
        ans2[i][j]=max(ans2[i][j], ans2[i-1][j]);
    }
}
int main()
{
    scanf("%d%lld%lld", &n, &C, &D);
    ll bi, pi;    char ch;
    rep(i,1,n)
    {
        scanf("%lld%lld%*c%c", &bi, &pi, &ch);
        if(ch=='C') c[++cnt1]=MP(pi, bi);
        else d[++cnt2]=MP(pi, bi);
    }
    Init();
    ll sum1=0;
    if(ans1[C][0] && ans2[D][0])
        sum1 = max(sum1, ans1[C][0]+ans2[D][0]);
    ll sum2=0, sum3=0;
    rep(i,1,cnt1)
    {
        ll  ret=C-c[i].fi;
        if(ret>0)
        {
            if(ans1[ret][0]==c[i].se)
            {
                if(ans1[ret][1])
                    sum2 = max(sum2, c[i].se+ans1[ret][1]);
            }
            else
            {
                if(ans1[ret][0])
                    sum2 = max(sum2, c[i].se+ans1[ret][0]);
            }
        }
    }
    rep(i,1,cnt2)
    {
        ll  ret=D-d[i].fi;
        if(ret>0)
        {
            if(ans2[ret][0]==d[i].se)
            {
                if(ans2[ret][1])
                    sum3 = max(sum3, d[i].se+ans2[ret][1]);
            }
            else
            {
                if(ans2[ret][0])
                    sum3 = max(sum3, d[i].se+ans2[ret][0]);
            }
        }
    }
    printf("%lld\n", max(sum1, max(sum2, sum3)));

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41289920/article/details/82533062