zoukankan      html  css  js  c++  java
  • 【ZJOI2020】序列【贪心】

    Description

    有一个长度为 (n) 的非负整数序列 (a_1, a_2, dots, a_n)。每一步你可以从以下三种操作中选择一种执行:

    • 选择一个区间 ([l, r]),将下标在这个区间里的所有数都减 1。
    • 选择一个区间 ([l, r]),将下标在这个区间里且下标为奇数的所有数都减 1。
    • 选择一个区间 ([l, r]),将下标在这个区间里且下标为偶数的所有数都减 1。

    求最少需要多少步才能将序列中的所有数都变成 0。

    (nle 10^5,a_ile 10^9)

    Solution

    首先题目的三种操作可以转化为两种操作:

    • 从某一点出发,尽可能向右延伸直到到达为 (0) 的位置,将经过的点全部减 (1)
    • 从某一点出发,依次将右侧与当前点奇偶性相同的点 (-1) ,直到到达为 (0) 的位置。

    考虑从左到右,将所有数变为 (0),设当前正在考虑 (a_i),如果 (a_{i+1})(a_i) 都不为 (0),那么直接从 (i) 出发执行一操作一定比执行二操作优,于是我们一直执行一操作直到 (a_i)(0)(a_{i+1})(0);然后若 (a_i ot= 0),再用二操作将 (a_i) 减到 (0)

    由于前面的操作会对当前点造成影响,不妨设可能会影响到当前点的一操作有 (x) 种,二操作有 (y) 种。

    (a_i>x+y) ,那么直接减去 (x+y)。否则 (x,y) 中有部分操作在这里就终止了,我们令 (k=x+y-a_i),然后先让 (x,y,a_i) 都减去 (k),然后看作给 (a_i) 增加了 (k) 次免费操作的机会,让它来决定是选一操作还是二操作,问题就迎刃而解了。但是 (x) 有可能小于 (k),那么 (k-x) 个二操作一定延伸不了,直接让 (y-=k-x,k=x) 即可。(y<k) 时同理。

    最终复杂度 (mathcal O(n))

    Code

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e5+10;
    typedef long long ll;
    int n,T;
    ll a[N],ans;
    int main(){
    	scanf("%d",&T);
    	while(T--){
    		scanf("%d",&n);
    		for(int i=1;i<=n;++i) scanf("%lld",&a[i]);
    		ll x=0,y=0,z=0;ans=0;
    		for(int i=2;i<=n+1;++i){
    			int d=0;
    			if(a[i]<x+y){
    				d=x+y-a[i];
    				if(x<d) y-=d-x,d=x;
    				if(y<d) x-=d-y,d=y;
    				x-=d;y-=d;a[i]-=d;
    			}
    			a[i]-=x+y;
    			ll tmp=min(a[i],a[i-1]);
    			x+=tmp;
    			a[i-1]-=tmp;a[i]-=tmp;ans+=tmp;
    			tmp=a[i-1];
    			z+=tmp;ans+=tmp;a[i-1]=0;
    			ans-=d;a[i]+=d;
    			swap(y,z);
    		}
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    rxjs 学习实践笔记
    封装localStorage、sessionStorage设置,获取,移除方法
    Angular实现类似vuex状态管理功能、全局数据管理与同步更新
    关于RxJS 处理多个Http请求 串行与并行方法
    vue插件汇总
    vue使用videojs控制后台m3u8数据请求
    NPOI winform读取Excel
    //邮件发送:
    定时任务框架Quartz.net
    系统日志控件 Log4NET
  • 原文地址:https://www.cnblogs.com/tqxboomzero/p/14885387.html
Copyright © 2011-2022 走看看