zoukankan      html  css  js  c++  java
  • Codeforces Round #642(div3) A-E题解

    A - Most Unstable Array

    构造长为n,和为m的数组a,使得相邻元素差的绝对值之和最大。即,需要构造形如(0,x,0,0..)的数组。

    • n == 1,ans = 0
    • n == 2,ans = m
    • n > 2,ans = 2 * m
    B - Two Arrays And Swaps

    a,b两数组将可以交换k次,最终使得a数组各元素和最大。将两数组排序,每次交换:若a中最小值小于b中最大值则交换,最后计算结果即可。

    C - Board Moves

    n*n个点,相邻的点之间可以移动,耗时为1,询问将所有点移动到一点需要的最短时间.

    比赛时的解法:

    • n为奇数时,其他点移动到中心点最优,模拟每一步的移动,计算。
    • n为偶数, 中心点选择 x or y == n / 2中的一个点即可,处理同上。(emm,做的太急,题中规定:n is odd...
    • 以上两种情况画个图会很清楚的看出来选择方案。

    官方:

    ​ 选中中心点后,有8个点可以1步到达,16个点2步...

    • ans = 1 * 8 + 2 * 16 + 3 * 24 + ... = 1 * 1 * 8 + 2 * 2 *8 + 3 * 3 * 8 + ...
    • 循环计算n / 2次,每一次的i * i求和,最终结果 * 8.
    D - Constructing the Array

    一个全0数组,初始l = 1,r = n,每一步中选择最长的连续靠左全0区间

    • 第i步,r - l + 1为奇数,a[l + r >> 1] = i; 否则,a[l + r - 1 >> 1] = i;

    • 使用优先队列存储各全0区间,其中r - l大的优先级最高,区间长度相等,l小的优先级高。

    int mid,idx,t,n,a[kN];
    //每次选择l r 最长全0序列 靠左 
    struct node{
    	int l,r;
    	friend bool operator < (node a,node b){//r - l大的优先级高 
    		if((a.r - a.l) == (b.r - b.l))  return a.l > b.l;//靠左,l小优先级高 
    		return (a.r - a.l) < (b.r - b.l);
    	}
    }cur;
    int main(void){
    	ios::sync_with_stdio(false);
    	cin.tie(0);cout.tie(0);
    	cin >> t;
    	priority_queue<node> q;
    	while(t--){
    		cin >> n;
    		cur.l = 1,cur.r = n;
    		q.push(cur);
    		for(int i = 1; i <= n; i++){
    			cur = q.top();
    			q.pop();
    			idx = cur.r - cur.l + 1;
    			if(cur.r == cur.l){
    				a[cur.r] = i;
    				continue;
    			}
    			if(idx & 1){
    				mid = cur.r + cur.l >> 1;
    				a[mid] = i;
    			}
    			else{
    				mid = cur.l + cur.r - 1 >> 1;
    				a[mid] = i;
    			}
    			q.push({cur.l,mid - 1});
    			q.push({mid + 1,cur.r});
    		}
    		for(int i = 1; i <= n; i++){
    			if(i != 1) cout << ' ';
    			cout << a[i];
    		}
    		cout << endl;
    		while(!q.empty()) q.pop(); 
    	}
        
    	return 0;
    } 
    
    E - K-periodic Garland

    n个灯组成了一个环,等长字符串表示灯的状态 - '0': 关闭。'1':开启。如果每对相邻的灯之间距离为k,则称为k周期。(0010010,001001 均可以,001010001,1001等则不可以),如果花环不是k周期,寻找最少的灯的状态改变个数。 -- 01串修改为相邻两1之间有k - 1个0.

    • 字符串分为k个周期子串,结果中的各个'1'的索引 mod k后的值相等。

    • '1'的位置选定后,其他位置的'1'修改为'0'。

    • 先记录原字符串中1的个数sum,初始答案赋值为sum(存在000..x or 00...0这样的合法序列,若需要修改的次数大于之前1的个数,之前修改为全0,次数更少,answer最大为sum)
      dp解法

    • dp(i,0 or 1)表示第i位为0 or 1时符合要求的最小操作次数,cnt[i]:前i位中,1的个数

    • dp(i,0) = min(dp(i - 1, 0),dp(i - 1, 1)) + s[i] != '0'

    • dp(i,1) = min(dp(i - k,1) + cnt( i - 1) - cnt[i - k],cnt[i - 1]) + s[i] != '1'//cnt[i - 1] - cnt[i - k] :(i - 1,i - k]中的1的个数,也可修改为00...01

    cin >> n >> k >> s;
    
    for(int i = 0; i < n; i++) cnt[i] = cnt[i - 1] + (s[i] - '0'),dp[i] = 0x3f3f3f3f;
    for(int i = 0; i < n; i++){
          if(i < k){
        	dp[i][1] = cnt[i - 1] + (s[i] == '0');//第一个周期,之前的1全部修改
            dp[i][0] = min(dp[ i - 1][1],dp[i - 1][0]) + (s[i] == '1')
          }else{
            dp[i][1] = min(dp[i - k][1] + cnt[i - 1] - cnt[i - k],cnt[i - 1]) + (s[i] == '0');
            dp[i][0] = min(dp[i - 1][1],dp[i - 1][1]) + (s[i] == '1');
        }
    }
    
    cout << min(dp[n - 1][0],dp[n - 1][1]) << endl;
    
  • 相关阅读:
    JDK API文档下载
    idea技巧:查看一个类的所有子类以及子类的子类并以层级关系显示
    Vue项目优化
    deepin 安装netcore 记录
    UOS 下的VScode 使用经验
    UOS操作系统磁盘空间不够一例
    SRPBatcher优化的原理
    我的UOS生活
    假如美国禁用了Unity3D和Unreal怎么办
    BGFX学习笔记01
  • 原文地址:https://www.cnblogs.com/honey-cat/p/12914304.html
Copyright © 2011-2022 走看看