51Nod 1672 扫描线 + 线段树/树状数组

来源:互联网 发布:淘宝卖家真实现状 编辑:程序博客网 时间:2024/06/10 21:23

题目大意,给定n个数字和m个区间,和km,从m个区间中选出恰好k个,使得他们的交的和最大,数字都是正数,n,m,k<=1e5。
题解:首先不难发现这个题没法直接做,STL上了个错的思想,即每个区间都+1然后对于被覆盖了k+次的区间做最大字段和,显然是错的。
考虑枚举答案的右端点,显然左端点越远越不可能是答案,而左端点越远效果越好。并且注意到一个区间是覆盖[l,r]当且仅当这个区间既覆盖l,又覆盖r。这样每次r+1,就把不覆盖r的区间删去,把覆盖了r的区间加上。然后考虑左端点,如果左端点被少于k个区间覆盖,那么l++。
最后用所有的合法的[l,r]更新答案即可,上述可用线段树或者树状数组实现,由于每个区间只会被计算一次,所以复杂度O(nlgn).
考试的时候多组数据。

#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>#include<vector>#define N 100010#define lint long longusing namespace std;struct segment{    int s,l,r,pt;    segment *ch[2];}*rt;inline int update_tags(segment* &rt,int v){    return rt->pt+=v,rt->s+=v;}inline int push_down(segment* &rt){    update_tags(rt->ch[0],rt->pt);    update_tags(rt->ch[1],rt->pt);    return rt->pt=0;}int build(segment* &rt,int l,int r){    rt=new segment;rt->l=l,rt->r=r;    rt->s=rt->pt=0;if(l==r) return 0;    int mid=(l+r)>>1;    build(rt->ch[0],l,mid);    build(rt->ch[1],mid+1,r);    return 0;}int Clear(segment* &rt){    rt->s=rt->pt=0;if(rt->l==rt->r) return 0;    Clear(rt->ch[0]),Clear(rt->ch[1]);return 0;}int update(segment* &rt,int s,int t,int v){    int l=rt->l,r=rt->r,mid=(l+r)>>1;    if(s<=l&&r<=t) return update_tags(rt,v);    if(rt->pt) push_down(rt);    if(s<=mid) update(rt->ch[0],s,t,v);    if(mid<t) update(rt->ch[1],s,t,v);    return 0;}int query(segment* &rt,int p){    int l=rt->l,r=rt->r,mid=(l+r)>>1;    if(l==r) return rt->s;    if(rt->pt) push_down(rt);    if(p<=mid) return query(rt->ch[0],p);    else return query(rt->ch[1],p);}int a[N];lint s[N],ans;vector<int> L[N],R[N];int main(){    int n,k,m;build(rt,1,N);    while(scanf("%d%d%d",&n,&k,&m)!=EOF)    {        for(int i=1;i<=n;i++) scanf("%d",&a[i]);        for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i];        for(int i=1;i<=n;i++) L[i].clear(),R[i].clear();        Clear(rt);ans=0LL;        for(int i=1;i<=m;i++)        {            int s,t;scanf("%d%d",&s,&t);            L[s].push_back(t),R[t].push_back(s);        }        for(int r=1,l=1;r<=n;r++)        {            for(int i=0;i<R[r-1].size();i++)                update(rt,R[r-1][i],r-1,-1);            for(int i=0;i<L[r].size();i++)                update(rt,r,L[r][i],1);            while(l<=r&&query(rt,l)<k) l++;            if(l<=r) ans=max(ans,s[r]-s[l-1]);        }        printf("%lld\n",ans);    }    return 0;}
阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 龙宫游玩攻略 龙宫奇经八脉怎么点 寻仙龙宫破阵顺序 两男一女双入龙宫 梦幻手游千万别玩龙宫 龙宽 疏楼龙宿 龙宿 高墙之内by龙宿一 中华龙将 龙将手机版 91玩龙将2 360龙将2 龙将手游 三国龙将传 龙将2 装备 龙将摸金符 龙将石头 龙将2幻浪 龙将2开服表 龙将斩千 龙将武将 紫霞龙将 龙将三国 龙将八爪吧 欢乐园龙将 龙将顾问 龙将太史慈 龙将打孔石 龙将2职业选择 龙将2媒体礼包 龙将v3多少钱 龙将2魔神吕布 龙将声望怎么获得 360龙将2开服表 星河龙将 狂潮大队长 龙将70金将对酒攻略 龙将武将大全 手游龙将礼包 三国争霸龙将 龙将起手技能