zoukankan      html  css  js  c++  java
  • 牛客小白月赛34 ACEF(待补)

    链接:https://ac.nowcoder.com/acm/contest/11211/A
    来源:牛客网

    A.

    题目描述

    大科学家dddd最近在研究转基因白菜,白菜的基因序列由一串大写英文字母构成,dddd经过严谨的推理证明发现,只有当白菜的基因序列呈按位非递减形式时,这株白菜的高附加值将达到最高,于是优秀的dddd开始着手修改白菜的基因序列,dddd每次修改基因序列的任意位需要的代价是11,dddd想知道,修改白菜的基因序列使其高附加值达到最高,所需要的最小代价的是多少。

    输入描述:

    第一行一个正整数n(1≤n≤1000000)
    第二行一个长度为n的字符串,表示所给白菜的基因序列
    保证给出字符串中有且仅有大写英文字母
    

    输出描述:

    输出一行,表示最小代价
    

    示例1

    输入

    复制

    5
    ACEBF
    

    输出

    复制

    1
    

    说明

    改成ACEEF或者ACEFF,都只用改动一个字符,所需代价最小为1
    

    懒得写了直接找了个最长不下降子序列的板子,求出来长度以后用n减一下即可。

    //最长不下降子序列nlogn  Song 
     
    #include<cstdio>
    #include<algorithm>
    #include <bits/stdc++.h>
    using namespace std;
     
    int a[1000005];
    int d[1000005];
     
    int main()
    {
        int n;
        scanf("%d",&n);
        string s;
        cin >> s;
        for (int i=1;i<=n;i++) {
        	a[i] = s[i - 1] - 'A';
    	}
        if (n==0)  //0个元素特判一下 
        {
            printf("0
    ");
            return 0;
        }
        d[1]=a[1];  //初始化 
        int len=1;
        for (int i=2;i<=n;i++)
        {
            if (a[i]>=d[len]) d[++len]=a[i];  //如果可以接在len后面就接上 
            else  //否则就找一个最该替换的替换掉 
            {
                int j=upper_bound(d+1,d+len+1,a[i])-d;  //找到第一个大于它的d的下标 
                d[j]=a[i]; 
            }
        }
        printf("%d
    ",n - len);    
        return 0;
    }
    
    

    链接:https://ac.nowcoder.com/acm/contest/11211/C
    来源:牛客网

    C.

    题目描述

    大科学家dddd最近在研究转基因白菜,白菜的基因序列由一串大写英文字母构成,dddd经过严谨的推理证明发现,只有当白菜的基因序列呈按位非递减形式时,这株白菜的高附加值将达到最高,于是优秀的dddd开始着手修改白菜的基因序列,dddd每次可以选择基因序列的一位进行修改,每次当她把一个字母xx修改成yy时,会产生∣x−y∣∣x−y∣(即xx与yy的ASCIIASCII码差值的绝对值)的改动偏移量,dddd希望,修改白菜的基因序列使其高附加值达到最高,并且基因序列的改动偏移量总和最小,她想知道最小的改动偏移量总和是多少。

    输入描述:

    第一行一个正整数n(1≤n≤1000000)
    第二行一个长度为n的字符串,表示所给白菜的基因序列
    保证给出字符串中有且仅有大写英文字母
    

    输出描述:

    输出一行,表示最小改动偏移量总和
    

    示例1

    输入

    复制

    5
    AEEBC
    

    输出

    复制

    5
    

    说明

    改成AEEEE或ACCCC偏移量总和最小
    改成AEEEE,偏移量总和为|B-E|+|C-E|=3+2=5
    改成ACCCC,偏移量总和为|E-C|+|E-C|+|B-C|=2+2+1=5
    所以最小偏移量总和为5
    

    直接暴力DP一下就完事了,转移方程见代码。

    #include <bits/stdc++.h>
    using namespace std;
    int dp[1000005][26];//第i个数为A + j的最小总花费 
    int n;
    int main() {
    	cin >> n;
    	string s;
    	cin >> s; 
    	memset(dp, 0x3f3f3f3f, sizeof(dp));
    	for(int i = 0; i < 26; i++) {
    		dp[1][i] = abs(s[0] - 'A' - i);
    	}
    	for(int i = 2; i <= n; i++) {
    		char c = s[i - 1];
    		for(int j = 0; j < 26; j++) {
    			for(int k = 0; k <= j; k++) {//单调不降的要求
    				dp[i][j] = min(dp[i][j], dp[i - 1][j - k] + abs((c - 'A') - j));
    			}
    		}
    	}
    	int ans = 0x3f3f3f3f;
    	for(int i = 0; i < 26; i++) {
    		ans = min(ans, dp[n][i]);
    	}
    	cout << ans;
    	return 0;
    } 
    

    E.

    链接:https://ac.nowcoder.com/acm/contest/11211/E
    来源:牛客网

    题目描述

    【题目描述】
    读入一个n∗nn∗n的矩阵,对于一个矩阵有以下两种操作
    11:顺时针旋180°180°
    22:关于行镜像

    [1234][13​24​]变成[3412][31​42​]给出qq个操作,输出操作完的矩阵

    输入描述:

    第一行一个数n(1≤n≤1000),表示矩阵大小
    接下来n行,每行n个数,描述矩阵,其中数字范围为[1,2000]
    一下来一行一个数q(1≤q≤100000),表示询问次数
    接下来q行,每行一个数x(x=1或x=2),描述每次询问
    

    输出描述:

    n行,每行n个数,描述操作后的矩阵
    

    示例1

    输入

    复制

    2
    1 2
    3 4
    1
    1
    

    输出

    复制

    4 3
    2 1
    

    示例2

    输入

    复制

    2
    1 2
    3 4
    1
    2
    

    输出

    复制

    3 4
    1 2
    

    易知顺时针旋转180度后(a[i][j]->a[n - i + 1][n - j + 1]),水平翻转后(a[i][j]->a[n - i + 1][j]),且这两个操作的性质与异或类似(操作两次不变)。又注意到第一个下标不管是哪种操作一定会变,第二个下标只有顺时针旋转会变,因此只需要统计这两种操作的奇偶性,然后最终的数组与原数组究竟是哪种对应关系即可。

    #include <bits/stdc++.h>
    using namespace std;
    int o[1005][1005], a[1005][1005], n, q, cnt1 = 0, cnt2 = 0;
    int main() {
    	cin >> n;
    	for(int i = 1; i <= n; i++) {
    		for(int j = 1; j <= n; j++) {
    			cin >> o[i][j];
    		}
    	}
    	cin >> q;
    	for(int i = 1; i <= q; i++) {
    		int op;
    		cin >> op;
    		if(op == 1) cnt1++;
    		else cnt2++;
    	}
    	for(int i = 1; i <= n; i++) {
    		for(int j = 1; j <= n; j++) {
    			if((cnt1 & 1) && (cnt2 & 1)) {
    				a[i][j] = o[i][n - j + 1];
    			} else if(cnt2 & 1) {
    				 a[i][j] = o[n - i + 1][j];
    			} else if(cnt1 & 1) {
    				a[i][j] = o[n - i + 1][n - j + 1];
    			} else {
    				a[i][j] = a[i][j] = o[i][j];
    			}
    		}
    	}
    	for(int i = 1; i <= n; i++) {
    		for(int j = 1; j <= n; j++) {
    			cout << a[i][j] << " ";
    		}
    		cout << endl;
    	}
    }
    

    F.

    链接:https://ac.nowcoder.com/acm/contest/11211/F
    来源:牛客网

    题目描述

    读入n,xn,x,给出nn个数a[1],a[2],……,a[n]a[1],a[2],……,a[n],求最小的区间[l,r][l,r],使a[l]+a[l+1]+……+a[r]≥xa[l]+a[l+1]+……+a[r]≥x,若存在相同长度区间,输出ll最小的那个

    输入描述:

    第一行两个数,n(1≤n≤10000000),x(1≤x≤10000)
    第二行n个数a[i](1≤a[i]≤1000)
    

    输出描述:

    输出符合条件l,r(保证有解)
    

    示例1

    输入

    复制

    10 20
    1 1 6 10 9 3 3 5 3 7
    

    输出

    复制

    3 5
    

    备注:

    双指针+队列维护一段区间并维护一个值(区间和)。当区间和小于x则把r右移同时更新sum,若大于等于x则不断左移l并更新sum和最终答案,直到区间和小于x,然后再指针右移并更新sum。代码写丑了调了半天==

    注意n很大,读入要用scanf。

    #include <bits/stdc++.h>
    #define int long long
    using namespace std;
    int n, x;
    int l = 1, r = 0;
    long long sum = 0;
    queue<int> q;
    int ans = 100000000, lmin = 100000000;
    signed main() {
    	cin >> n >> x;
    	for(int i = 1; i <= n; i++) {
    		int ai;
    		scanf("%lld", &ai);
    		if(sum < x) {
    			sum += 1ll * ai;
    			r++;
    			q.push(ai);
    		} else {
    			while(sum >= 1ll * x && l <= r) {
    				if(r - l + 1 < ans) {
    					ans = r - l + 1;
    					lmin = l;
    				} else if(r - l + 1 == ans) {
    					if(l < lmin) {
    						lmin = l;
    					}
    				}
    				l++;
    				int now = q.front();
    				q.pop();
    				sum -= 1ll * now;
    			}
    			r++;
    			sum += 1ll * ai;
    			q.push(ai);
    		}
    	}
    	while(sum >= 1ll * x && l <= r) {//为了判末尾
    		if(r - l + 1 < ans) {
    			ans = r - l + 1;
    			lmin = l;
    		} else if(r - l + 1 == ans) {
    			if(l < lmin) {
    				lmin = l;
    			}
    		}
    		l++;
    		int now = q.front();
    		q.pop();
    		sum -= 1ll * now;
    	}
    	if(n == 1) cout << 1 << " " << 1;
    	else cout << lmin << " " << lmin + ans - 1;
    	return 0;
    }
    //5 9
    //1 1 1 1 9
    //
    //3 6
    //2 4 6
    
  • 相关阅读:
    剑指offer:复杂链表的复制
    剑值offer:最小的k个数
    剑指offer:第一个只出现一次的字符
    剑指offer:树的子结构
    leetcode 240搜索二维矩阵
    leetcode 22括号生成
    leetcode 79 单词搜索
    leetcode 17电话号码的字母组合
    leetcode 78子集
    leetcode 105从前序与中序遍历序列构造二叉树
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/14824166.html
Copyright © 2011-2022 走看看