zoukankan      html  css  js  c++  java
  • P4756-Added Sequence【斜率优化】

    正题

    题目链接:https://www.luogu.com.cn/problem/P4756


    题目大意

    给出序列(a),设(f(l,r)=|sum_{i=l}^ra_i|)

    (m)次询问若序列(a)全部加上某个数(x),求最大的(f(l,r))

    (1leq n,mleq 2 imes 10^5),强制在线(或许)


    解题思路

    求一次前缀和的话设为(s_i),那么(f(l,r)=|s_r-s_l|)。其实拆开绝对值不难发现这样就去掉了(l,r)的限制,答案就是(max{s_r}-min{s_l})了。

    然后集体加上某个数(x)的话,原来的(s_i)就变为了(s_i+i imes x)了。

    然后就是给出(x)求最大和最小的(s_i+i imes x)。经典的斜率优化把戏。

    维护一个上凸壳,一个下凸壳,然后在上面二分就好了。

    时间复杂度(O(n+mlog n))


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const ll N=2e5+10;
    ll n,m,top,toq,f[N],s[N],t[N];
    ll calc(ll x,ll i)
    {return x*i+f[i];} 
    signed main()
    {
    	scanf("%lld%lld",&n,&m);
    	for(ll i=1;i<=n;i++){
    		scanf("%lld",&f[i]);f[i]+=f[i-1];
    		while(top&&(f[i]-f[s[top]])*(s[top]-s[top-1])>=(f[s[top]]-f[s[top-1]])*(i-s[top]))top--;s[++top]=i;
    		while(toq&&(f[i]-f[t[toq]])*(t[toq]-t[toq-1])<=(f[t[toq]]-f[t[toq-1]])*(i-t[toq]))toq--;t[++toq]=i;
    	}
    	ll pre=0,x;
    	while(m--){
    		scanf("%lld",&x);x=(x+pre)%(4*n+1)-2*n;
    		ll l=0,r=top-1;pre=0;
    		while(l<=r){
    			ll mid=(l+r)>>1;
    			if(calc(x,s[mid])>calc(x,s[mid+1]))r=mid-1;
    			else l=mid+1;
    		}
    		pre+=calc(x,s[l]);
    		l=0;r=toq-1;
    		while(l<=r){
    			ll mid=(l+r)>>1;
    			if(calc(x,t[mid])<calc(x,t[mid+1]))r=mid-1;
    			else l=mid+1;
    		}
    		pre-=calc(x,t[l]);
    		printf("%lld
    ",pre);
    	}
    	return 0;
    }
    
  • 相关阅读:
    js 实现 间隙滚动效果
    js实现无缝滚动
    js 实现弹出层效果
    jQuery实现网页定位导航
    右侧定位的样式
    jQuery实现点击按钮展开和收起
    js实现点击按钮控制展开与收起.
    【BZOJ1202】[HNOI2005]狡猾的商人 带权并查集
    【BZOJ1067】[SCOI2007]降雨量 RMQ+特判
    【BZOJ1367】[Baltic2004]sequence 左偏树
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/14628667.html
Copyright © 2011-2022 走看看