远光杯 L题.捕鱼达人(线段树优化带权lis)

捕鱼达人
balabala一大堆问题描述. 其实就是找带权序列里面找不下降序列权值最大的一段.
我们可以把负数的权值都舍去,因为对答案没有贡献. 这样子处理过后.我们考虑怎么找要的答案. 一种做法是把一条鱼拆成几条权值为1的鱼.这样子就是普通的lis了.这里就不谈了.
线段树的做法.
对于当前这条小鱼,应该把它接到颜值小于等于它的鱼链里价值最大的那一条鱼链后面. 怎么找这个鱼链就有讲究了. 我们用一个线段树去维护每一个鱼链的最大价值.因为这里的颜值取值范围比较小.所以可以不用离散化,直接对颜值建树. 然后每次只要找颜值0-当前颜值里面最大的一个就好了. 然后更新当前节点. 注意要更新的位置是当前颜值的节点
代码

#pragma GCC optimize(3)
#define LL long long
#define pq priority_queue
#define ULL unsigned long long
#define pb push_back
#define mem(a,x) memset(a,x,sizeof a)
#define pii pair<int,int>
#define pll pair<long long,long long>
#define pdd pair<double,double>
#define db double
#define fir(i,a,b) for(int i=a;i<=b;++i)
#define afir(i,a,b) for(int i=a;i>=b;--i)
#define ft first
#define vi vector<int>
#define sd second
#define ALL(a) a.begin(),a.end()
#define L 2*i
#define R 2*i+1
#include <bits/stdc++.h>

using namespace std;
const int N = 1e4+10;
const int mod = 9901;

LL gcd(LL a,LL b){return b == 0 ? a : gcd(b,a%b);}
struct Tree{
	int l,r,v;
}tree[N*8];
int a[N],v[N];
void build(int i,int l,int r){
	tree[i] = {l,r,0};
	if(l>=r) return;
	int mid = l+r>>1;
	build(L,l,mid);
	build(R,mid+1,r);
}
void add(int i,int p,int v){
	if(tree[i].l == tree[i].r){
		tree[i].v = max(tree[i].v,v);
		return;
	}
	int mid = tree[i].l + tree[i].r >> 1;
	if(p <= mid) add(L,p,v);
	else add(R,p,v);
	tree[i].v = max(tree[L].v,tree[R].v);
}
int query(int i,int l,int r){
	if(tree[i].l >= l && tree[i].r <= r) return tree[i].v;
	int mid = tree[i].l + tree[i].r >> 1;
	if(r <= mid) return query(L,l,r);
	if(l > mid) return query(R,l,r);
	return max(query(L,l,mid),query(R,mid+1,r));
}
int main(){
	int t,tot=0;
	cin >> t;
	while(t--){
		int n;
		printf("Case #%d: ",++tot);
		cin >> n;
		int ans = -1e9;
		vi va,sa;
		fir(i,1,n){
			cin >> a[i];
			v[i] = a[i]/10000;
			a[i] %= 10000;
			ans = max(v[i],ans);
			if(v[i] <= 0) continue;
			va.pb(v[i]);
			sa.pb(a[i]+1);
		}
		if(ans <= 0){
			cout << ans << endl;
			continue;
		}
		build(1,1,1e4+5);
		fir(i,0,(int)sa.size()-1){
			int cur = query(1,1,sa[i]);
			add(1,sa[i],cur+va[i]);
			ans = max(ans,cur+va[i]);
		}
		build(1,1,1e4+5);
		afir(i,(int)sa.size()-1,0){
			int cur = query(1,1,sa[i]);
			add(1,sa[i],cur+va[i]);
			ans = max(ans,cur+va[i]);
		}
		cout << ans << endl;
	}
	
	return 0;
}	

猜你喜欢

转载自blog.csdn.net/weixin_45590210/article/details/105949348