牛客小白月赛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\n");
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",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][1324]变成[3412][3142]给出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