Codeforces1250C Trip to Saint Petersburg 线段树

题意

有个人要去圣彼得堡旅游,在圣彼得堡每天要花(k)块钱,然后在圣彼得堡有(n)个兼职工作(l_i,r_i,p_i),如果这个人在(l_i)(r_i)这个时间段都在圣彼得堡,那么他就可以赚到(p_i)块钱,现在他要规划旅游计划(left[ L,R ight]),表示他会在(L)到达,在(R)离开,要求给出赚钱最多的方案。

解题思路

线段树区间加法,单点最大值及取得最大值的下标。

将兼职工作挂到右端点上,然后枚举离开的时间,枚举到(i)时,就对区间(left[1,i ight])进行区间减(k),然后对于以(i)为右端点的询问((l,r,p))对区间(left[1,l ight])进行区间加(p)。这样,对于线段树维护的序列,记为(A)(A_j)即表示第(j)天到达,第(i)天离开能获取的最大利润,然后每次更新即可。

解题代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,int> pi;
typedef tuple<ll,int,int> tp;
const int maxn=2e5+5;
int n;
ll k;

pi v[maxn<<2];
ll tag[maxn<<2];
void push_down(int x){
	if(tag[x]){
		tag[x<<1]+=tag[x]; tag[x<<1|1]+=tag[x];
		v[x<<1].first+=tag[x]; v[x<<1|1].first+=tag[x];
		tag[x]=0;	
	}
}
void build(int x,int l,int r){
	if(l==r){
		v[x]=make_pair(0LL,l);
		return;
	}
	int mid=(l+r)>>1;
	build(x<<1,l,mid); build(x<<1|1,mid+1,r);
	v[x]=max(v[x<<1],v[x<<1|1]);
}
void update(int x,int l,int r,int L,int R,ll val){
	if(l==L && r==R){
		tag[x]+=val;
		v[x].first+=val;
		return;
	}
	push_down(x);
	int mid=(l+r)>>1;
	if(R<=mid)update(x<<1,l,mid,L,R,val);
	else if(L>mid)update(x<<1|1,mid+1,r,L,R,val);
	else{
		update(x<<1,l,mid,L,mid,val);	
		update(x<<1|1,mid+1,r,mid+1,R,val);
	}
	v[x]=max(v[x<<1],v[x<<1|1]);
}
pi query(int x,int l,int r,int L,int R){
	if(l==L && r==R)return v[x];
	push_down(x);
	int mid=(l+r)>>1;
	if(R<=mid)return query(x<<1,l,mid,L,R);
	else if(L>mid)return query(x<<1|1,mid+1,r,L,R);
	return max(query(x<<1,l,mid,L,mid),query(x<<1|1,mid+1,r,mid+1,R));	
}

vector<tp>q[maxn];
vector<int>ans;
int main()
{
	scanf("%d %lld",&n,&k);
	int l,r; ll p;
	build(1,1,2e5);
	for(int i=1;i<=n;i++){
		scanf("%d %d %lld",&l,&r,&p);
		q[r].push_back(make_tuple(p,l,i));
	}
	p=0;int L,R;
	for(int i=1;i<=2e5;i++){
		update(1,1,2e5,1,i,-k);
		for(tp P:q[i])update(1,1,2e5,1,get<1>(P),get<0>(P));
		if(v[1].first>p){
			p=v[1].first; L=v[1].second; R=i;
		}
	}
	if(p<=0)printf("0
");
	else{
		for(int i=L;i<=R;i++){
			for(tp P:q[i])if(get<1>(P)>=L)ans.push_back(get<2>(P));
		}
		printf("%lld %d %d %d
",p,L,R,(int)ans.size());
		for(int id:ans)printf("%d ",id);
	}
	return 0;	
}
原文地址:https://www.cnblogs.com/zengzk/p/11767155.html