【51 Nod】堆积木【树状数组】

在这里插入图片描述


解题思路

跟求最长不下降子系列的题差不多,那道题变量是顺序和数值大小,这道题是两条边长。

先把一个积木分三个情况存下来(有无数个积木,不用担心同一个使用多次),然后先按长(宽)为关键字排序,按序给每个编号(即离散化),注意长(宽)相同的编号也要相同。然后再按宽(长)排一次序,剩下的做法就是求最长不下降子系列的做法,但注意当宽(长)相同时,要先把他们都算出来,再分别插入,不然会算重。


代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;

ll n,cnt,t,x,y,z,ans,tree[300010],f[300010];

struct c{
	ll a,b,c,id;
}a[300010];

bool cmp1(c l,c r)
{
	if(l.a==r.a) return l.b<r.b;
	return l.a<r.a;
}

bool cmp2(c l,c r)
{
	if(l.b==r.b)return l.a<r.a;
	return l.b<r.b;
}

void add(ll x,ll c)
{
	for(int i=x;i<=cnt;i+=i&(-i))
		tree[i]=max(tree[i],c);
}

ll find(ll x)
{
	ll ans=0;
	for(int i=x;i;i-=i&(-i))
		ans=max(ans,tree[i]);
	return ans;
}

int main(){
	scanf("%lld",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%lld%lld%lld",&x,&y,&z);
		a[++cnt].a=min(x,y),a[cnt].b=max(x,y),a[cnt].c=z;
		a[++cnt].a=min(z,y),a[cnt].b=max(z,y),a[cnt].c=x;
		a[++cnt].a=min(x,z),a[cnt].b=max(x,z),a[cnt].c=y;
	}
	sort(a+1,a+cnt+1,cmp1);
	a[1].id=++t;
	for(int i=2;i<=cnt;i++)
	{
		if(a[i-1].a!=a[i].a)
		a[i].id=++t;
		else 
		a[i].id=t;
	}
	sort(a+1,a+cnt+1,cmp2);
	for(int i=1;i<=cnt;i++)
	{
		int j=i;
		while(j<=cnt&&a[j].b==a[i].b)
		{
			f[j]=find(a[j].id-1)+a[j].c;
			j++;
		}
		for(int k=i;k<j;k++)
			add(a[k].id,f[k]);
		i=j-1;
	}
	for(int i=1;i<=cnt;i++)
		ans=max(ans,f[i]);
	printf("%lld",ans);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值