• 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;	
    }
    
  • 相关阅读:
    Oracle 获取表结构信息
    EasyUI layout动态设置Split属性
    jquery easyui-datagrid 如何清空数据
    ORacle 复制表
    aspx调用webmethod
    RDLC添加链接
    Nginx 负载均衡 ip_hash , hash key(consistent) url_hash, least_conn
    Nginx 提升吞吐量利器 Keeplived
    Nginx Gzip 的正确使用
    Nginx 切割日志
  • 原文地址:https://www.cnblogs.com/zengzk/p/11767155.html
Copyright © 2020-2023  润新知