zoukankan      html  css  js  c++  java
  • 2017-3-12四校联考

    感觉这天一整天有点头昏脑涨,晚上吃完饭就睡过去了连博客也没写

    T1大判断,T3看上去比较裸的二分完线段树优化DP,就T2看上去比较有意思,没想到最后正解还要用什么积分orz。最后没交,补一道T3,其他没什么打的欲望。

    T3.序列

    题目大意:给定正整数m和两个长度为n的序列对(ai,bi),要求把序列分成若干段,满足:1.若i<j且i与j不在同一段,则bi>aj;2.每一段a的最大值之和不超过m。要求划分方案满足条件的同时每一段b的和的最大值最小。(n<=100000)

    思路:条件1说明只有前i个b的最小值大于后n-i个a的最大值,i才能作为段的末尾,预处理一下可以把不能分段的缩成一个点(新的a取段中a最大值,b取段中b的和),这样我们之后就不用考虑条件1了。我们二分答案,DP求出每一段b之和都不超过当前二分出的答案时最小的各段a最大值之和。f[i]表示序列前i个分成若干段最小的a最大值之和,则f[i]=min(f[j]+max(a[i+1]~a[j]))(sum(b[i+1]~b[j])<=当前二分的答案),可以用线段树大力维护,总复杂度O(nlogn^2)。

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    #define ll long long
    inline ll read()
    {
        ll x;char c;
        while((c=getchar())<'0'||c>'9');
        for(x=c-'0';(c=getchar())>='0'&&c<='9';)x=(x<<3)+(x<<1)+c-'0';
        return x;
    }
    #define MN 100000
    #define INF (1LL<<60)
    #define L (x<<1)
    #define R (x<<1^1)
    int n,a[MN+5],ma[MN+5];
    ll b[MN+5],sb[MN+5],mb[MN+5],f[MN+5];
    struct node{int l,r,mx,mk;ll mf,ms;}t[MN*4+5];
    inline void up(int x)
    {
        t[x].mx=max(t[L].mx,t[R].mx);
        t[x].mf=min(t[L].mf,t[R].mf);
        t[x].ms=min(t[L].ms,t[R].ms);
    }
    inline void mark(int x,int z)
    {
        t[x].mx=t[x].mk=z;
        t[x].ms=t[x].mf+z;
    }
    #define down(x) if(t[x].mk)mark(L,t[x].mk),mark(R,t[x].mk),t[x].mk=0
    void build(int x,int l,int r)
    {
        t[x].l=l;t[x].r=r;t[x].mk=0;
        if(l==r){t[x].mx=0;t[x].mf=t[x].ms=INF;return;}
        build(L,l,l+r>>1);build(R,(l+r>>1)+1,r);up(x);
    }
    void renew1(int x,int k,ll f)
    {
        if(t[x].l==t[x].r){t[x].mf=t[x].ms=f;return;}
        down(x);renew1(k>t[x].l+t[x].r>>1?R:L,k,f);up(x);
    }
    void renew2(int x,int r,int a)
    {
        if(t[x].mx<a&&t[x].r==r){mark(x,a);return;}
        if(t[x].l==t[x].r)return;down(x);
        int mid=t[x].l+t[x].r>>1;
        if(r<=mid)renew2(L,r,a);
        else if(t[R].mx>=a)renew2(R,r,a);
        else renew2(L,mid,a),renew2(R,r,a);
        up(x);
    }
    ll query(int x,int l,int r)
    {
        if(t[x].l==l&&t[x].r==r)return t[x].ms;
        down(x);
        int mid=t[x].l+t[x].r>>1;
        if(r<=mid)return query(L,l,r);
        if(l>mid)return query(R,l,r);
        return min(query(L,l,mid),query(R,mid+1,r));
    }
    ll check(ll x)
    {
        int i;
        build(1,1,n);renew1(1,1,0);
        for(i=1;i<=n;++i)
        {
            renew1(1,i,f[i-1]);
            renew2(1,i,a[i]);
            f[i]=query(1,lower_bound(sb,sb+n+1,sb[i]-x)-sb+1,i);
        }
        return f[n];
    }
    int main()
    {
        freopen("sequence.in","r",stdin);
        freopen("sequence.out","w",stdout);int i,j,k,x;ll m,l=0,r,mid,ans;
        n=read();m=read();
        for(mb[0]=INF,i=1;i<=n;++i)a[i]=read(),mb[i]=min(mb[i-1],b[i]=read());
        for(i=n;i;--i)ma[i]=max(ma[i+1],a[i]);
        for(i=1,k=0;i<=n;i=j)
        {
            for(j=i,x=r=0;j==i||mb[j-1]<=ma[j];++j)x=max(x,a[j]),r+=b[j];
            a[++k]=x;b[k]=r;
        }
        for(n=k,i=1;i<=n;++i)sb[i]=sb[i-1]+b[i],l=max(l,b[i]);
        for(r=INF;l<=r;)if(check(mid=l+r>>1)<=m)ans=mid,r=mid-1;else l=mid+1;
        cout<<ans;
        fclose(stdin);fclose(stdout);return 0;
    }
  • 相关阅读:
    ajax 跨域 Access-Control-Allow-Origin
    关于 请求参数 传递时 参数字符串里面包含 特殊符号的 解决~
    鼠标滚动事件
    js 选择随机数
    html 关于一行两列 高度不定的实现(不用table)
    关于php跨域操作(主域不同)
    写规范的javascript脚本代码 之for in
    windows服务等获取文件路径文件目录方法
    C#如何在控制台应用程序中加入配置文件
    easyui Microsoft JScript 运行时错误: “JSON”未定义
  • 原文地址:https://www.cnblogs.com/ditoly/p/20170312C.html
Copyright © 2011-2022 走看看