• CF1425E Excitation of Atoms


    http://codeforces.com/problemset/problem/1425/E

    (sum_i) 为前缀和,(gain_i)(max sum_n-sum_{j-1}-D_j,jge i)(gain2_i)(max sum_n-sum_{j-1}-D_j,jle i)

    k=0

    显然 (ans=max(gain_1,0))

    k>1

    构造,对于一个 (i),将 (E_i) 改为 (1),将 (E_{i-1}) 改为 (i+1)
    这样可以激发所有原子,只要将 (i) 选为 (D_i) 最小的即可

    k=1

    分两种情况

    (E_i) 向前改,此时肯定改为 (1),同样代价把前面都选上才会最优
    这样如果要激发 ([1,i]),只需花费 (min=min D_j,jle i) 的代价
    如果要激发 ([i+1,n]) 中的某个子段,用 (gain) 计算
    答案为 (sum_i-min+max(gain_{i+1},0)),枚举所有 (i) 取最大值

    (E_{i-1}) 向后改,此时肯定改为 (i+1),否则少取中间跳过的一段也不会最优
    如果激发点 (jge i),答案为 (gain_i),和 (k=0) 的类似
    如果激发点 (j<i),那么会激发 ([j,n]) 所有点除去 (i),再考虑 (i) 要不要单独激发一下,答案是 (gain2_{i-1}-min(D_i,A_i))
    单独再激发一下 (i) 的情况已经包含了两个激发点同时在 (i) 的前后,不用单独考虑这种两个激发点的情况了
    仍然枚举 (i) 取最大值

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<map>
    #define reg register
    inline int read(){
    	register int x=0;register int y=0;
    	register char c=getchar();
    	while(c<'0'||c>'9'){if(c=='-')y=1;c=getchar();}
    	while(c>='0'&&c<='9') x=x*10+c-48,c=getchar();
    	return y?-x:x;
    }
    #define N 100006
    int n;
    long long sum[N],a[N],gain[N],gain_[N];
    long long d[N];
    int main(){
    	n=read();int k=read();
    	for(reg int i=1;i<=n;i++) sum[i]=sum[i-1]+(a[i]=read());
    	for(reg int i=1;i<=n;i++) d[i]=read();
    	for(reg int i=1;i<=n;i++) gain[i]=sum[n]-sum[i-1]-d[i],gain_[i]=std::max(gain_[i-1],gain[i]);
    	for(reg int i=n-1;i;i--) gain[i]=std::max(gain[i],gain[i+1]);
    	if(!k) return printf("%lld",std::max(gain[1],0ll)),0;
    	if(k>1){
    		long long ans=sum[n]-d[1];
    		for(reg int i=2;i<n;i++) ans=std::max(ans,sum[n]-d[i]);
    		ans=std::max(ans,a[n]-d[n]);
    		printf("%lld",std::max(ans,0ll));
    		return 0;
    	}
    	long long ans=0;
    	long long min=std::min(d[1],d[2]);
    	for(reg int i=2;i<n;i++){
    		ans=std::max(ans,sum[i]-min+std::max(0ll,gain[i+1]));//向前改 
    		min=std::min(min,d[i+1]);
    	}
    	for(reg int i=2;i<n;i++){
    		ans=std::max(ans,std::max(gain[i],gain_[i-1]-std::min(a[i],d[i])));//向后改
    //		ans=std::max(ans,gain[])
    	}
    	for(reg int i=2;i<=n;i++) ans=std::max(ans,sum[n]-sum[i-1]-d[i]);
    	printf("%lld",ans);
    	return 0;
    }
    
  • 相关阅读:
    软工结对第一次作业
    16061023-软件工程第1次作业
    OO最后一次总结
    OO第三次博客作业
    OO第二次博客作业
    OO第一次博客
    提问回顾与个人总结
    软件工程第一次阅读作业
    test个人博客
    软件工程结对作业
  • 原文地址:https://www.cnblogs.com/suxxsfe/p/13904117.html
Copyright © 2020-2023  润新知