• Codeforces Round #636(div.3) A-D题解


    A.Candies
    • 输入一个数字n,输出满足(k > 1) && ((2 ^ k) - 1) * x == n的任意x值,由于n < 1e9,k由2开始枚举,找到符合条件的x输出。
    B.Balanced Array

    输入数组长度n,问是否存在这样的一个数组:1. 数组前一半均为偶数,后一半均为奇数;2.前一半和后一半数组中元素的和相等

    • 后一半数组中为奇数,与前一半数组和相等即n/2 也是偶数
    • 若满足上面的条件,从2开始枚举 n/2 个偶数输出并求和
    • 从1开始枚举输出n/2 - 1个奇数并求和,最后输出之前偶数和与奇数和的差值
    C. Alternating Subsequence

    ​ 做的时候读题太粗心,只看到了最大和。WA了之后读了好几次题也没看到最长这个优先级最高的条件,一直在错误的地方修改......

    • 题目中会输入一组长为n的数组,要求输出一个最长的交错子序列[1]的最大和

    • 贪心:遍历数组,每个连续的同号子串取最值。

    	cin >> t;
    	while(t--){
    		cin >> n;
    		ans = mx = 0;
    		for(int i = 0; i < n; i++){
    			cin >> a[i];
    			if(!i || a[i] * a[i - 1] < 0){
    				ans += mx;
    				mx = a[i]; 
    			}else{
    				mx = max(mx,a[i]);
    			}
    		}
    		cout << ans + mx << endl;
    	}
    
    D. Constant Palindrome Sum

    输入由n个整数组成的数组a,和整数k,替换数组中de一些元素为[1,k]中的任一元素,使数组满足:

    1. a[i] <= k
    2. a[i] + a[n - i + 1] = x,即对称的元素和为定值( 2 <= x <= 2k)
    • 求最小替换元素的个数

    对于确定的x,每对元素的交换次数确定

    1. a + b = x

    2. x ∈[min(a,b) + 1,max(a,b) + k + 1),半开半闭的区间方便合并,获得最小和,最大和,差分,此区间 + 1--起始位置 + 2,左边界(闭)-1,右边界(开) +1

    3. 其它

       交换次数存在一个最大值,当x = k + 1,为 n / 2(所有元素值的区间[1,k]);对每一对元素,计算交换次数为1的区间,使用差分思想通过cnt数组在区间外+2,区间内+1,对每一对元素的和特殊处理;在枚举完所有的元素对后,将差分数组cnt修改为前缀和即为相应x的替换次数,ans 初始化为n / 2,遍历cnt数组寻找最小替换次数。。。
      
    const int kN = 2e5 + 10,kM = 4e5 + 5;
    int t,n,k,l,r,ans,a[kN],cnt[kM];
    //替换最少数量的元素,数组中对称元素和满足 a[i] + a[n - i + 1] = x;x为某个定值 
    int main(void){
    	ios::sync_with_stdio(false);
    	cin.tie(0);cout.tie(0);
    	cin >>t;
    	while(t--){
    		memset(cnt,0,sizeof(cnt));
    		cin >> n >> k;
    		for(int i = 1; i <= n; i++) cin >> a[i];
    		for(int i = 1; i <= n / 2; i++){
    			l = min(a[i],a[n - i + 1]) + 1;
    			r = max(a[i],a[n - i + 1]) + k + 1;//区间左闭右开,便于合并
    			cnt[1] += 2;//差分 边界[2,l) 需要两次 
    			cnt[l]--;//[l,r] 一次 
    			cnt[r]++;
    			cnt[a[i] + a[n - i + 1]]--;//0
    			cnt[a[i] + a[n - i + 1] + 1]++; 
    		} 
    		for(int i = 2; i <= 2 * k; i++) cnt[i] += cnt[i - 1];//计算各个x值的替换次数 
    		ans = n / 2;
    		for(int i = 1; i <= 2 * k; i++) ans = min(ans,cnt[i]);
    		cout << ans << endl;
    	}
    	return 0;
    }
    

    1. 正负交替 ↩︎

  • 相关阅读:
    JS 按钮下一步(onclick点击事件)
    socketserver模块
    进程
    僵尸进程和孤儿进程
    守护进程
    互斥锁
    进程间通信=>IPC机制
    生产者消费者模型
    线程
    守护线程
  • 原文地址:https://www.cnblogs.com/honey-cat/p/12802986.html
Copyright © 2020-2023  润新知