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;
    
  • 相关阅读:
    Apache Ant 1.9.1 版发布
    Apache Subversion 1.8.0rc2 发布
    GNU Gatekeeper 3.3 发布,网关守护管理
    Jekyll 1.0 发布,Ruby 的静态网站生成器
    R语言 3.0.1 源码已经提交到 Github
    SymmetricDS 3.4.0 发布,数据同步和复制
    beego 0.6.0 版本发布,Go 应用框架
    Doxygen 1.8.4 发布,文档生成工具
    SunshineCRM 20130518发布,附带更新说明
    Semplice Linux 4 发布,轻量级发行版
  • 原文地址:https://www.cnblogs.com/honey-cat/p/12914304.html
Copyright © 2011-2022 走看看