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

来源:互联网 发布:软件详细设计模板 java 编辑:程序博客网 时间:2024/06/08 11:10

题目链接: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;}