1.CodeForces 1788A. One and Two
题意:给定长度为n的数组,数组由1,2组成,找出k使得a1*a2*...ak=a(k+1)*...an
2<=n<=1000;
思路:
记录数组两侧2的数量,若相等,则找到k
#include<iostream>
using namespace std;
const int maxn = 1e3 + 10;
int a[maxn];
int main()
{
ios::sync_with_stdio(false);
int t;
cin >> t;
while (t--){
int n;
cin >> n;
int flag = 0, a2 = 0;
for (int i = 1; i <= n; i++){
cin >> a[i];
if (a[i] == 2)
a2++;//记录整个数组中2的数量
}
if (a2 & 1){//奇数不能平分
cout << -1 << endl;
continue;
}
int ans = 0;
for (int i = 1; i <= n; i++){
if (a[i] == 2){
flag++;//记录遇到的2的数量
a2--;//2的总数对应-1
}
if (flag == a2){
ans = i;
break;
}
}
cout << ans << endl;
}
return 0;
}
2.AtCoder abc288_cC - Don’t be cycle
题意:给定一张无向图,要求删除一些边,使得没有环
思路:
没有环即一棵树,跑一遍生成树,删掉边=总边-生成树的边
#include<iostream>
using namespace std;
const int maxn = 1e6 + 10;
int n, m,cnt,ans;
int head[maxn];
int vis[maxn];
struct edge {
int to, next;
}e[maxn];
void insert(int u,int v) { //链式前向星
e[++cnt].to = v;
e[cnt].next = head[u];
head[u] = cnt;
}
void dfs(int x) {
vis[x] = 1;
for (int i = head[x]; i; i = e[i].next) {
int y = e[i].to;
if (vis[y] == 0) {
dfs(y);
ans++;
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin >> n >> m;
for (int i = 1; i <= m; i++) {
int u, v;
cin >> u >> v;
insert(u, v);
insert(v, u);
}
for (int i = 1; i <= n; i++) {
if (vis[i] == 0) {
dfs(i);
}
}
cout << m-ans << '\n';
return 0;
}
3.Codeforces 1788B. Sum of Two Numbers
题意:将n拆分成x,y,满足x+y=n;x,y位数和之差不大于0
思路:
将n拆分成位数,若为偶数,则n/2,n/2对分乘倍数,若为奇数n/2+1,n/2交替分乘倍数
#include<iostream>
#include<math.h>
using namespace std;
int t;
int a[20];
int cnt = 0;
void fun(int x) {
cnt=0;
while (x) {
a[++cnt] = x % 10;
x /= 10;
}
}
int main()
{
ios::sync_with_stdio(false);
cin >> t;
while (t--) {
long long n;
cin >> n;
fun(n);
long long x=0,y=0,flag = 1;
for (int i = 1; i <= cnt; i++) {
if (a[i] % 2) {
if (flag % 2) {
x += ((a[i] / 2) + 1) * pow(10, i - 1);
y += (a[i] / 2) * pow(10, i - 1);
flag++;
}
else{
x += (a[i] / 2) * pow(10, i - 1);
y += ((a[i] / 2)+1) * pow(10, i - 1);
flag++;
}
}
else {
x += (a[i] / 2) * pow(10, i-1);
y += (a[i] / 2) * pow(10, i - 1);
}
}
cout << x << ' ' << y<<'\n';
}
return 0;
}
4.AtCoder abc288D - Range Add Query
5.CodeForces 1791E. Negatives and Positives
题意:给定长度n的数组,可以有若干次操作使得ai和a(i + 1)的数字正负变化,问最终数组和最大是多大。
解法1思路:
dp[i][0]表示前i个数中,且第i个数没有改变正负性的所有方案的最大值
dp[i][1]表示前i个数中,且第i个数有改变正负性的所有方案的最大值,
#include<iostream>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 10;
int a[maxn];
ll dp[maxn][2];
int main() {
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
dp[2][0] = a[1] + a[2], dp[2][1] = -a[1] + -a[2];
for (int i = 3; i <= n; i++) {
dp[i][0] = max(dp[i - 1][0], dp[i - 1][1]) + a[i];
//上一步两种状态
//dp[i - 1][0]表示i-1个数未改变正负,dp[i - 1][1]表示i-1个数已经改变正负
dp[i][1] = max(dp[i - 1][0] -2*a[i - 1], dp[i - 1][1]+ 2*a[i - 1]) - a[i];
//上一步两种状态
//dp[i - 1][0] - 2 * a[i - 1]表示a[i-1]改变正负
//dp[i - 1][0] + 2 * a[i - 1]表示a[i-1]未改变
//这种写法牵扯到第一步从i=2开始的相邻转符
}
cout<< max(dp[n][0], dp[n][1])<<'\n';
}
return 0;
}
解法2思路:
记录负数的个数,如果是偶数,那么都可以转正,
如果是奇数,那么剩下一个负数,转移给绝对值最小的那个数,如果那个数是正数,需要改变符号。
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 5;
ll cnt;
ll a[maxn];
int main()
{
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
ll Min=0x3f3f3f3f;
cnt = 0;
for (int i = 1; i <= n; i++) {
cin >> a[i];
if (a[i] < 0)
cnt++;//记录负数的个数
Min = min(abs(a[i]), Min);//记录绝对值最小的数
}
ll sum = 0;
if (cnt % 2){//奇数
bool flag=0;
for (int i = 1; i <= n; i++){
if (abs(a[i]) == Min && !flag)
{
if (a[i] > 0) a[i] *= -1;
sum += a[i], flag=1;
}
else sum += abs(a[i]);
}
cout << sum << '\n';
}
else{//偶数
for (int i = 1; i <= n; i++) {
sum += abs(a[i]);
}
cout << sum << '\n';
}
}
return 0;
}