• JOISC2017C 手持ち花火


    Link
    首先二分答案(v)
    考虑这样一个结论:最优解一定是(K)不动,其它人往(K)这里跑,跑到了之后先不点燃,等(K)的位置上每有一个人的火熄灭就点燃下一个。
    那么如果我们能够点燃区间([L,R])的所有烟火,就需要存在一个扩展路径上的所有(l,r)满足:

    [x_l+vT(r-l)ge x_r-vT(r-l) ]

    移项得

    [x_l-2vTlge x_r-2vTr ]

    (a_i=x_i-2vTi),上式就是(a_lge a_r)
    因此,存在一种点燃方案,等价于存在(p_1cdots p_n,P_1cdots P_n),使得(p_1=P_1=k,p_n=1,P_n=n),随着(i)递增每次(p_i)减一或者(P_i)加一,并且保证(a_{p_i}ge a_{P_i})
    也就是存在一个扩展路径使得路径上的每对(l,r)满足(a_lge a_r)
    假如我们现在有区间([l,r]),我们要对它扩展。
    考虑如何扩展(l),若存在(i),使得
    1:(a_ige a_l)
    2:(forall jin[i,l],a_jge a_r)
    条件2显然是必须满足的,条件一是为了使接下来(r)一定更远。
    那么我们就可以进行一次把左端点扩展到(i)的扩展。
    每次扩展时找到最右边的能扩展的(i)即可。
    扩展(r)也是同样的操作。
    如果某次我们(l,r)都没有扩展,并且都是因为条件2不满足,那么这个(v)一定不合法。
    如果是因为条件1不满足,我们无能为力。
    接下来考虑如何解决这个问题。
    我们求出(a_1sim a_{K-1})中最大值(a_{pl})(a_{K+1}sim a_n)中的最小值(pr)
    显然如果我们能够扩展到([pl,pr]),那么接下来1条件一定不满足,并且说明过程中2条件都满足,这一部分是合法的。
    我们再考虑将左端点(l)设为(1),右端点(r)设为(n),向内扩展。扩展过程就是上面的反过来。
    如果我们还能扩展到([pl,pr]),那么说明过程中2条件都满足,也就是这个(v)合法。
    我们要计算的有(vTi),这个东西显然可能爆long long。
    我们注意到,当(vTge10^9)时,一定可以点燃所有烟花,所以一开始把二分的右端点设为(frac{10^9}{T}+1)即可。

    #include<bits/stdc++.h>
    #define LL long long
    #define mid ((l+r)>>1)
    using namespace std;
    namespace IO
    {
        char ibuf[(1<<21)+1],*iS,*iT;
        char Get(){return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++);}
        int read(){int x=0;char ch=Get();while(ch>57||ch<48)ch=Get();while(ch>=48&&ch<=57)x=x*10+(ch^48),ch=Get();return x;}
    }
    using namespace IO;
    const int N=100007,inf=1e9;
    int n,K,T,x[N];
    LL a[N];
    int check(int v)
    {
        int i,l,r,L,R,ql,qr,f;
        for(i=1;i<=n;++i) a[i]=1ll*x[i]-2ll*T*v*i;
        if(a[1]<a[n]) return 0;
        for(ql=qr=K,i=K-1;i;--i) if(a[i]>=a[ql]) ql=i;
        for(i=K+1;i<=n;++i) if(a[i]<=a[qr]) qr=i;
        for(l=r=K;l^ql||r^qr;)
        {
    	f=0,L=l,R=r;
            for(;L>ql&&a[L-1]>=a[r];) if(a[--L]>=a[l]) break;
            if(L<l&&a[L]>=a[l]) f=1,l=L;
            for(;R<qr&&a[R+1]<=a[l];) if(a[++R]<=a[r]) break;
    	if(R>r&&a[R]<=a[r]) f=1,r=R;
            if(!f) return 0;
        }
        for(l=1,r=n;l^ql||r^qr;)
        {
    	f=0,L=l,R=r;
            for(;L<ql&&a[L+1]>=a[r];) if(a[++L]>=a[l]) break;
            if(L>l&&a[L]>=a[l]) f=1,l=L;
    	for(;R>qr&&a[R-1]<=a[l];) if(a[--R]<=a[r]) break;
    	if(R<r&&a[R]<=a[r]) f=1,r=R;
            if(!f) return 0;
        }
        return 1;
    }
    int main()
    {
        n=read(),K=read(),T=read();int i,l=0,r=inf/T+1,ans;
        for(i=1;i<=n;++i) x[i]=read();
        while(l<=r) check(mid)? ans=mid,r=mid-1:l=mid+1;
        printf("%d
    ", ans);
    }
    
  • 相关阅读:
    jquery select操作和联动操作
    chrome 31删除输入框的历史记录
    14、python开发之路-并发编程之I/O模型
    13、python开发之路-并发编程之多线程
    12、python全栈之路-并发编程之多进程
    11、python全栈之路-网络编程
    10、python全栈之路-面向对象进阶
    9、python全栈之路-模块与包
    8、python全栈之路-初识面向对象
    6、python全栈之路-常用模块
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12342182.html
Copyright © 2020-2023  润新知