[Codeforces div3-498] problem solution

Posted by Matt Phelps on Sun, 09 Jan 2022 13:30:10 +0100

Codeforces div3-498 Problem solution

A. Adjacent Replacements

The problem is relatively simple. If the number N is an odd number, it will remain unchanged after transformation. If the number is an even number, it will become N - 1

#include <stdio.h>

const int maxn=1005;
int a[maxn];
int n;
 
void work()
{
    scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		if(a[i]%2)
		{
			printf("%d ",a[i]);
		}
		else
			printf("%d ",a[i]-1);
	}
}
 
int main()
{
	work();
	return 0;
}

B. Polycarp's Practice

First of all, according to the meaning of the question, we can determine that the selected number must be the largest K of the input numbers, so all we need to do is find the K largest numbers, record their positions and divide them according to their positions. The method I use here is troublesome. In addition, I use a container to store the location. In fact, only one pair type can solve it

#include <cstdio>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
using namespace std;

const int maxn = 2003;

map<int,queue<int> > pos;

bool cmp(int a,int b)
{
	return a > b;
}

int n,k;
vector<int> problems(maxn);

void input()
{
	scanf("%d%d",&n,&k);
	for(int i = 0;i < n;i++)
	{
		scanf("%d",&problems[i]);
		pos[problems[i]].push(i);
	}
}

void work()
{
	vector<int> opro = problems;
	vector<int> ans;
	sort(opro.begin(),opro.end(),cmp);
	int power = 0;
	int old = -1;
	for(int i = 0;i < k;i++)
	{
		power += opro[i];
		ans.push_back(pos[opro[i]].front());
		pos[opro[i]].pop();
	}
	printf("%d\n",power);
	sort(ans.begin(),ans.end());
	int left = 0;
	for(int i = 0;i < ans.size();i++)
	{
		if(i != ans.size() - 1)
		{
			printf("%d ",ans[i] - left + 1);
			left = ans[i] + 1;
		}else
		{
			printf("%d",n - left);
		}
	}
}

int main()
{
	input();
	work();
	return 0;
}

C. Three Parts of the Array

For this problem, first of all, the first part must be on the left side of the array, and the second part must be on the right side of the array. At the same time, the middle part can be empty, so the method of double pointers can be adopted. One pointer is in front, the other pointer is in the back, and it stops when it meets or the sum of parts is the same.

#include <cstdio>
#include <vector>
using namespace std;

const int maxn = 2 * 1e5 + 3;

vector<int> nums(maxn);

int n;

void input()
{
	scanf("%d",&n);
	for(int i = 0;i < n;i++)
	{
		scanf("%d",&nums[i]);
	}
}

void work()
{
	int left = 0;
	int right = n - 1;
	long long int suml = nums[left];
	long long int sumr = nums[right];
	long long int max = 0;

	while(left < right)
	{
		if(suml > sumr)
		{
			right--;
			sumr += nums[right];
		}else if(suml < sumr)
		{
			left++;
			suml += nums[left];
		}else
		{
			if(suml > max)
			{
				max = suml;
			}
			left++;
			right--;
			sumr += nums[right];
			suml += nums[left];
		}
	}
	printf("%lld",max);
}

int main()
{
	input();
	work();
	return 0;
}

D. Two Strings Swaps

First understand the meaning of the question. In fact, each exchange involves only four elements, namely a[i],a[n - i -1],b[i],b[n - i - 1], among which there are several different situations

1. The four elements are the same
2. The four elements are different
3. The three elements are the same
4. The two elements are the same
5. The two elements are the same, and the other two elements are different
Among them, for 1 and 4, pretreatment is not required, for 3, pretreatment is only required once, for 2, pretreatment is required twice, and for 5, we also need to discuss it by situation. When a[i] = a[n - i - 1], because we can only process a, pretreatment needs to be performed twice at this time, a [i]= A [n - I - 1] only needs to be performed once.

#include <cstdio>
#include <map>

using namespace std;

const int maxn = 1e5 + 7;

map<char,int> ans;

int n;
char a[maxn],b[maxn];

void input()
{
	scanf("%d",&n);
	getchar();
	scanf("%s",a);
	scanf("%s",b);
}

void work()
{
	int cnt = 0;
	int mid = 0;
	if(n % 2)
	{
		mid = n / 2 + 1;
	}else
	{
		mid = n / 2;
	}
	for(int i = 0;i < mid;i++)
	{
		ans[a[i]]++;
		ans[b[i]]++;
		if(n - i - 1 != i)
		{
			ans[a[n - i - 1]]++;
			ans[b[n - i - 1]]++;
		}
		else{
			if(ans[a[i]] % 2)
			{
				cnt++;
			}
			break;
		}
		int temp = ans[a[i]] | ans[a[n - i - 1]] | ans[b[i]] | ans[b[n - i -1]];
		if(ans[a[i]] == 3 || ans[a[n - i - 1]] == 3 || ans[b[i]] == 3 || ans[b[n - i - 1]] == 3)
		{
			cnt++;
		}else if(a[i] == a[n - i - 1] && b[i] != b[n - i - 1])
		{
			cnt += 2;
		}else if(b[i] == b[n - i - 1] && a[i] != a[n - i - 1])
		{
			cnt ++;
		}else if(ans[a[i]] == 1 && ans[a[n - i - 1]] == 1 && ans[b[i]] == 1 && ans[b[n - i - 1]] == 1)
		{
			cnt += 2;
		}else if(temp == 3)
		{
			cnt++;
		}	
		ans.clear();
	}
	printf("%d",cnt);
}

int main()
{
	input();
	work();
	return 0;
}	

E. Military Problem

What is required in the title is to find the k-th node after dfs from the i-th node. Then we only need to perform a dfs at the source node at the beginning, and record the occurrence order n of each node in the search_ i. Then access the k-th node after the i-th node, that is, access the n-th node_ I + K nodes.

#include <cstdio>
#include <vector>

using namespace std;

int n,k;
const int maxn = 2 * 1e5 + 7;
int currentOrder;

vector<vector<int> > officer(maxn);
vector<int> preorder(maxn);
vector<int> maxSize(maxn);
vector<int> preorder2Index(maxn);

void dfs(int index)
{
	preorder[index] = currentOrder;
	preorder2Index[currentOrder] = index;
	currentOrder++;	
	for(int i = 0;i < officer[index].size();i++)
	{
		dfs(officer[index][i]);
	}
	maxSize[index] = currentOrder - 1;
}

void input()
{
	scanf("%d%d",&n,&k);
	int temp = 0;
	currentOrder = 0;
	for(int i = 2;i <= n;i++)
	{
		scanf("%d",&temp);
		officer[temp].push_back(i);
	}
}

void work()
{
	int p,q;
	for(int i = 0;i < k;i++)
	{
		scanf("%d%d",&p,&q);	

		q += preorder[p] - 1;
		if(q > maxSize[p])
		{
			printf("-1\n");
		}else
		{
			printf("%d\n",preorder2Index[q]);
		}
	}
}

int main()
{
	input();
	dfs(1);
	work();
	return 0;
}

F. Xor-Paths

According to the meaning of the question, we have two choices for each step. We can take up to N + m - 2 steps from (1,1) to (n,m). That is, if we go from beginning to end, there are 2^(n + m - 2) cases, which obviously will timeout. So we need to change our thinking. Here we use the method of meeting halfway. Start from (1,1) node and (n,m) node at the same time. Take half the distance on both sides, i.e. (n + m - 2) / 2), record the XOR value when reaching the (i,j) node, and finally compare the XOR operation with k.

#include <cstdio>
#include <vector>
#include <map>

using namespace std;

int n,m;
int half;
long long int ans;
long long int target;
long long int cnt = 0;
long long int maps[23][23];
map<long long int, int> v[23][23];

void input()
{
	scanf("%d%d%lld",&n,&m,&target);
	half = (n + m - 2) / 2;
	long long int temp;
	ans = 0;
	for(int i = 0;i < n;i++)
	{
		for(int j = 0;j < m;j++)
		{
			scanf("%lld",&maps[i][j]);
		}
	}
}

void calclf(int x, int y, long long int val, int cnt)
{
	val ^= maps[x][y];
	if(cnt == half)
	{
		v[x][y][val]++;
		return;
	}
	if(x + 1 < n)
	{
		calclf(x + 1, y, val, cnt + 1);
	}
	if(y + 1 < m)
	{
		calclf(x, y + 1, val, cnt + 1);
	}
}

void calcrg(int x, int y, long long int val, int cnt)
{
	if(cnt == n + m - 2 - half)
	{
		if(v[x][y].count(target ^ val))
		{
			ans += v[x][y][target ^ val];
		}
		return;
	}
	if(x > 0)
	{
		calcrg(x - 1, y, val ^ maps[x][y], cnt + 1);
	}
	if(y > 0)
	{	
		calcrg(x, y - 1, val ^ maps[x][y], cnt + 1);
	}
}


void work()
{
	calclf(0,0,0,0);	
	calcrg(n - 1, m - 1,0,0);
	printf("%lld",ans);
}

int main()
{
	input();
	work();
	return 0;
}

Topics: Algorithm CodeForces