• [300iq Contest 1-D]Dates


    传送门

    Description

    每个妹子匹配一个时间区间,每个时间最多选择(a_i)个妹子,每个妹子有一个快乐值,最大化总快乐值

    Solution

    贪心,从大往小取,能取则取
    判断是否可以有完美匹配:根据Hall定理,只要满足任意一个区间的匹配集合大于区间大小即可
    可以等价的判断匹配的区间是否大于区间大小,因为不合法的情况必然包含在一个区间中
    可以用线段树区间加减(用于维护下标的变化)+求max和min来判断合法性


    Code 

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    #define reg register
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
        return x*f;
    }
    #define ls x<<1
    #define rs x<<1|1
    const int MN=3e5+5,inf=0x3f3f3f3f;
    ll N,M,a[MN],g[MN],L[MN],R[MN],id[MN];
    ll ans;
    bool cmp(int x,int y){return g[x]>g[y];}
    struct node{int ma,mi,val,p,lz;}T[MN<<2];
    void up(int x)
    {
        T[x].ma=max(T[ls].ma,T[rs].ma);
        T[x].mi=min(T[ls].mi,T[rs].mi);
        T[x].val=max(T[ls].val,T[rs].val);
        T[x].val=max(T[x].val,T[rs].ma-T[ls].mi);
    }
    void upd(int x,int v){T[x].ma+=v;T[x].mi+=v;T[x].p+=v;T[x].lz+=v;}
    void down(int x){if(!T[x].lz)return;upd(ls,T[x].lz);upd(rs,T[x].lz);T[x].lz=0;}
    void Build(int x,int l,int r)
    {
        if(l==r)
        {
            L[l]=a[read()-1];R[l]=a[read()];g[l]=read(),id[l]=l;
            T[x].ma=-inf,T[x].mi=inf;T[x].val=-2*inf;return;
        }
        int mid=(l+r)>>1;
        Build(ls,l,mid);Build(rs,mid+1,r);up(x);
    }
    
    void md1(int x,int l,int r,int a,int v)
    {
        if(l==r)
        {
            if(v==1) T[x].val=(T[x].ma=T[x].p-R[l])-(T[x].mi=T[x].p-L[l]);
            else T[x].ma=-inf,T[x].mi=inf,T[x].val=-2*inf;
            return;
        }
        int mid=(l+r)>>1;down(x);
        a<=mid?md1(ls,l,mid,a,v):md1(rs,mid+1,r,a,v);up(x);
    }
    void md2(int x,int l,int r,int a,int b,int v)
    {
        if(l==a&&r==b){upd(x,v);return;}
        int mid=(l+r)>>1;down(x);
        if(b<=mid)md2(ls,l,mid,a,b,v);
        else if(a>mid)md2(rs,mid+1,r,a,b,v);
        else md2(ls,l,mid,a,mid,v),md2(rs,mid+1,r,mid+1,b,v);up(x);
    }
    void add(int x,int v){md2(1,1,M,x,M,v);md1(1,1,M,x,v);}
    
    int main()
    {
        M=read(),N=read();reg int i;
        for(i=1;i<=N;++i)a[i]=read()+a[i-1];
        Build(1,1,M);std::sort(id+1,id+M+1,cmp);
        for(i=1;i<=M;++i)
        {
            add(id[i],1);
            if(T[1].val<=-1)ans+=g[id[i]];
            else add(id[i],-1);
        }
        return 0*printf("%lld
    ",ans);
    }
    


    Blog来自PaperCloud,未经允许,请勿转载,TKS!

  • 相关阅读:
    Spring的事务管理
    C#的WinForm中制作饼状图和柱状图
    .net+mssql制作抽奖程序思路及源码
    C#中简单调用MD5方法以及MD5简介
    【好文翻译】一步一步教你使用Spire.Doc转换Word文档格式
    C#调用C/C++动态库 封送结构体,结构体数组
    【好文翻译】测试必看:使用Spire.XLS来生成自动化报表!
    浅析C#基于TCP协议的SCOKET通信
    C# RSA和Java RSA互通
    C#创建windows服务搭配定时器Timer使用实例(用代码做,截图版)
  • 原文地址:https://www.cnblogs.com/PaperCloud/p/11773885.html
Copyright © 2020-2023  润新知