Wannafly模拟赛3-F 监视任务(贪心+线段树区间更新)

题目链接:https://www.nowcoder.com/acm/contest/13/F




题解:把所有约束按照右端点排序。

 这样每一个前面的约束区间[l1,r1],与后面的一个约束区 间[l2,r2]的交,一定为[max(l1,l2),r1]。 

对于排序后的区间依次满足约束,假设当前枚举到的约束现在没有满足,

就不断把对应区间中最右端的0改为1。 这些过程可以用线段树维护来完成。

#include<set>      
#include<map>         
#include<stack>                
#include<queue>                
#include<vector>        
#include<string>     
#include<time.h>    
#include<math.h>                
#include<stdio.h>                
#include<iostream>                
#include<string.h>                
#include<stdlib.h>        
#include<algorithm>       
#include<functional>        
using namespace std;                
#define ll long long          
#define inf 1000000000           
#define mod 1000000007                
#define maxn  500005   
#define lowbit(x) (x&-x)                
#define eps 1e-9  
struct node
{
	int l,r,k;
}a[maxn*2];
int n,m,sum[maxn*5],lazy[maxn*5];
bool comp(node a,node b)
{
	return a.r<b.r;
}
void pushdown(int l,int r,int id)
{
	if(lazy[id])
	{
		int mid=(l+r)/2;
		lazy[id*2]=1;
		sum[id*2]=mid-l+1;
		lazy[id*2+1]=1;
		sum[id*2+1]=r-mid;
		lazy[id]=0;
	}
}
int update(int id,int L,int R,int l,int r,int val)
{
	if(val<=0)
		return 0;
	if(L>=l && R<=r)
	{
		if(R-L+1-sum[id]<=val)
		{
			val-=R-L+1-sum[id];
			lazy[id]=1;
			sum[id]=R-L+1;
			return val;
		}
	}
	pushdown(L,R,id);
	int mid=(L+R)/2;
	if(r>mid)
		val=update(id*2+1,mid+1,R,l,r,val);
	if(l<=mid)
		val=update(id*2,L,mid,l,r,val);
	sum[id]=sum[id*2]+sum[id*2+1];
	return val;
}
int query(int id,int L,int R,int l,int r)
{
	if(L>=l && R<=r)
		return sum[id];
	pushdown(L,R,id);
	int mid=(L+R)/2,res=0;
	if(l<=mid)
		res+=query(id*2,L,mid,l,r);
	if(r>mid)
		res+=query(id*2+1,mid+1,R,l,r);
	return res;
}
int main(void)
{
	int i;
	scanf("%d%d",&n,&m);
	for(i=1;i<=m;i++)
		scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].k);
	sort(a+1,a+m+1,comp);
	for(i=1;i<=m;i++)
		update(1,1,n,a[i].l,a[i].r,a[i].k-query(1,1,n,a[i].l,a[i].r));
	printf("%d\n",query(1,1,n,1,n));
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值