Codeforces Round #550 (Div.3)

A. Diverse Strings


题目:

A string is called diverse if it contains consecutive (adjacent) letters of the Latin alphabet and each letter occurs exactly once. For example, the following strings are diverse: "fced", "xyz", "r" and "dabcef". The following string are not diverse: "az", "aa", "bad" and "babc". Note that the letters 'a' and 'z' are not adjacent.

Formally, consider positions of all letters in the string in the alphabet. These positions should form contiguous segment, i.e. they should come one by one without any gaps. And all letters in the string should be distinct (duplicates are not allowed).

You are given a sequence of strings. For each string, if it is diverse, print "Yes". Otherwise, print "No".

Input
The first line contains integer n (1≤n≤100), denoting the number of strings to process. The following n lines contains strings, one string per line. Each string contains only lowercase Latin letters, its length is between 1 and 100, inclusive.

Output
Print n lines, one line per a string in the input. The line should contain "Yes" if the corresponding string is diverse and "No" if the corresponding string is not diverse. You can print each letter in any case (upper or lower). For example, "YeS", "no" and "yES" are all acceptable.

思路:

题目意思是给出一段字符串,要求字符串中所含有的字母连续且不能重复。
做法:排序后判断即可。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
char a[105];
int vis[1000];
int main()
{
	int n;
	scanf("%d", &n);
	while (n--)
	{
		scanf("%s", a);
		int len = strlen(a);
		int flag = 0;
		for (int i = 0; i < len; i++)
		{
			vis[i] = a[i] - 'a' + 1;
		}
		sort(vis, vis + len);
		for (int i = 0; i < len-1; i++)
		{
			if (vis[i] == vis[i + 1] || vis[i] + 1 != vis[i + 1])
			{
				flag = 1;
				break;
			}
		}
		if (flag == 1)
			printf("no\n");
		else printf("Yes\n");
	}
}

B.Parity Alternated Deletions


题目:

Polycarp has an array a consisting of n integers.

He wants to play a game with this array. The game consists of several moves. On the first move he chooses any element and deletes it (after the first move the array contains n−1 elements). For each of the next moves he chooses any element with the only restriction: its parity should differ from the parity of the element deleted on the previous move. In other words, he alternates parities (even-odd-even-odd-... or odd-even-odd-even-...) of the removed elements. Polycarp stops if he can't make a move.

Formally:

If it is the first move, he chooses any element and deletes it;
If it is the second or any next move:
if the last deleted element was odd, Polycarp chooses any even element and deletes it;
if the last deleted element was even, Polycarp chooses any odd element and deletes it.
If after some move Polycarp cannot make a move, the game ends.
Polycarp's goal is to minimize the sum of non-deleted elements of the array after end of the game. If Polycarp can delete the whole array, then the sum of non-deleted elements is zero.

Help Polycarp find this value.

Input
The first line of the input contains one integer n (1≤n≤2000) — the number of elements of a.

The second line of the input contains n integers a1,a2,…,an (0≤ai≤106), where ai is the i-th element of a.

Output
Print one integer — the minimum possible sum of non-deleted elements of the array after end of the game.

思路:

题意是给出一个数组,先删除一个奇数或者偶数,如果删除了奇数,下一个删除一个偶数,如果删除了偶数,下一个删除一个奇数,如此往复,直至没有奇数或偶数删除,要剩下的元素最小。
贪心,分为奇数组,和偶数组,剩下的肯定是元素多的那组。排序后加上元素多的那组剩下的即可。

#include <iostream>
#include <algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<map>
using namespace std;
int a[2005],b[2005];
int n;
int main()
{
	scanf("%d", &n);
	int q = 0, p = 0;
	for (int i = 0; i < n; i++)
	{
		int ini;
		scanf("%d", &ini);
		if (ini % 2 == 0)
			a[q++] = ini;
		else b[p++] = ini;
	}
	sort(a, a + q);
	sort(b, b + p);
	if (q > p+1)
	{
		int key1=0;
		for (int i = 0; i < q - p - 1; i++)
			key1 += a[i];
		printf("%d\n", key1);
	}
	else if (p > q + 1)
	{
		int key1 = 0;
		for (int i = 0; i < p - q - 1; i++)
			key1 += b[i];
		printf("%d\n", key1);
	}
	else
	{
		printf("0\n");
	}
}

C.Two Shuffled Sequences


题目:

Two integer sequences existed initially — one of them was strictly increasing, and the other one — strictly decreasing.

Strictly increasing sequence is a sequence of integers [x1<x2<⋯<xk]. And strictly decreasing sequence is a sequence of integers [y1>y2>⋯>yl]. Note that the empty sequence and the sequence consisting of one element can be considered as increasing or decreasing.

They were merged into one sequence a. After that sequence a got shuffled. For example, some of the possible resulting sequences a for an increasing sequence [1,3,4] and a decreasing sequence [10,4,2] are sequences [1,2,3,4,4,10] or [4,2,1,10,4,3].

This shuffled sequence a is given in the input.

Your task is to find any two suitable initial sequences. One of them should be strictly increasing and the other one — strictly decreasing. Note that the empty sequence and the sequence consisting of one element can be considered as increasing or decreasing.

If there is a contradiction in the input and it is impossible to split the given sequence a to increasing and decreasing sequences, print "NO".

Input
The first line of the input contains one integer n (1≤n≤2⋅105) — the number of elements in a.

The second line of the input contains n integers a1,a2,…,an (0≤ai≤2⋅105), where ai is the i-th element of a.

Output
If there is a contradiction in the input and it is impossible to split the given sequence a to increasing and decreasing sequences, print "NO" in the first line.

Otherwise print "YES" in the first line and any two suitable sequences. Note that the empty sequence and the sequence consisting of one element can be considered as increasing or decreasing.

In the second line print ni — the number of elements in the strictly increasing sequence. ni can be zero, in this case the increasing sequence is empty.

In the third line print ni integers inc1,inc2,…,incni in the increasing order of its values (inc1<inc2<⋯<incni) — the strictly increasing sequence itself. You can keep this line empty if ni=0 (or just print the empty line).

In the fourth line print nd — the number of elements in the strictly decreasing sequence. nd can be zero, in this case the decreasing sequence is empty.

In the fifth line print nd integers dec1,dec2,…,decnd in the decreasing order of its values (dec1>dec2>⋯>decnd) — the strictly decreasing sequence itself. You can keep this line empty if nd=0 (or just print the empty line).

ni+nd should be equal to n and the union of printed sequences should be a permutation of the given sequence (in case of "YES" answer).

思路:

题意是给一个序列,将它拆成两个序列,一个严格递增,一个严格递减。
先排序,如果相同元素大于2个肯定就不能拆了,排完序后先从小到大加入递增序列,遇到相同的就加入递减序列,最后输出即可。

#include <iostream>
#include <algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
using namespace std;
int n;
int a[200005];
int ans1[200005], ans2[200005];
int cnt1, cnt2;
int main()
{
	scanf("%d", &n);
	for (int i = 0; i < n; i++)
	{
		scanf("%d", &a[i]);
	}
	sort(a, a + n);
	int flag = 0;
	int i;
	for (i = 0; i < n; i++)
	{
		if (a[i] == a[i + 1])
		{
			if (a[i + 1] == a[i + 2]&&i<n-1)
			{
				flag = 1;
				break;
			}
		}
		else 
			ans1[cnt1++] = a[i],a[i]=-1;
	}
	for (int i = n - 1; i >= 0; i--)
	{
		if (a[i] == -1)
			continue;
		ans2[cnt2++] = a[i];
	}
	if (flag == 1)
		printf("NO\n");
	else
	{
		printf("YES\n");
		printf("%d\n", cnt2);
		if (cnt2 == 0)printf("\n");
		else
		{
			for (int i = cnt2-1; i >=0; i--)
			{
				printf("%d", ans2[i]);
				if (i != 0)printf(" ");
			}
			printf("\n");
		}
		printf("%d\n", cnt1);
		if (cnt1 == 0)printf("\n");
		else
		{
			for (int i = cnt1 - 1; i >= 0; i--)
			{
				printf("%d", ans1[i]);
				if (i != 0)printf(" ");
			}
			printf("\n");
		}
	}
}

D.Equalize Them All


题目:

You are given an array a consisting of n integers. You can perform the following operations arbitrary number of times (possibly, zero):

Choose a pair of indices (i,j) such that |i−j|=1 (indices i and j are adjacent) and set ai:=ai+|ai−aj|;
Choose a pair of indices (i,j) such that |i−j|=1 (indices i and j are adjacent) and set ai:=ai−|ai−aj|.
The value |x| means the absolute value of x. For example, |4|=4, |−3|=3.

Your task is to find the minimum number of operations required to obtain the array of equal elements and print the order of operations to do it.

It is guaranteed that you always can obtain the array of equal elements using such operations.

Note that after each operation each element of the current array should not exceed 1018 by absolute value.

Input
The first line of the input contains one integer n (1≤n≤2⋅105) — the number of elements in a.

The second line of the input contains n integers a1,a2,…,an (0≤ai≤2⋅105), where ai is the i-th element of a.

Output
In the first line print one integer k — the minimum number of operations required to obtain the array of equal elements.

In the next k lines print operations itself. The p-th operation should be printed as a triple of integers (tp,ip,jp), where tp is either 1 or 2 (1 means that you perform the operation of the first type, and 2 means that you perform the operation of the second type), and ip and jp are indices of adjacent elements of the array such that 1≤ip,jp≤n, |ip−jp|=1. See the examples for better understanding.

Note that after each operation each element of the current array should not exceed 1018 by absolute value.

If there are many possible answers, you can print any.

#include <iostream>
#include <algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
using namespace std;
int map[200005];
int a[200005];
int n;
int main()
{
	scanf("%d", &n);
	int maxn = 0;
	for (int i = 1; i <= n; i++)
	{
		scanf("%d", &a[i]);
		map[a[i]]++;
		maxn = max(maxn, a[i]);
	}
	int ans = 0,key;
	for (int i = 0; i <= maxn; i++)
	{
		if (ans < map[i])
		{
			key = i;
			ans = map[i];
		}
	}
	int po;
	for (int i = 1; i <= n; i++)
	{
		if (key == a[i])
		{
			po = i;
			break;
		}
	}
	printf("%d\n", n-ans);
	for (int i = po-1; i >0; i--)
	{
		if (a[i] == key)
			continue;
		if (a[i] > key)
			printf("2 %d %d\n", i, i+1);
		else
			printf("1 %d %d\n", i, i+1);
	}
	while (a[po] == a[po + 1]&&po<n)
		po++;
	for (int i = po+1; i <= n; i++)
	{
		if (a[i] == key)
			continue;
		if (a[i] > key)
			printf("2 %d %d\n", i, i-1);
		else
			printf("1 %d %d\n", i, i-1);
	}
}

E.Median String


题目:

You are given two strings s and t, both consisting of exactly k lowercase Latin letters, s is lexicographically less than t.

Let's consider list of all strings consisting of exactly k lowercase Latin letters, lexicographically not less than s and not greater than t (including s and t) in lexicographical order. For example, for k=2, s="az" and t="bf" the list will be ["az", "ba", "bb", "bc", "bd", "be", "bf"].

Your task is to print the median (the middle element) of this list. For the example above this will be "bc".

It is guaranteed that there is an odd number of strings lexicographically not less than s and not greater than t.

Input
The first line of the input contains one integer k (1≤k≤2⋅105) — the length of strings.

The second line of the input contains one string s consisting of exactly k lowercase Latin letters.

The third line of the input contains one string t consisting of exactly k lowercase Latin letters.

It is guaranteed that s is lexicographically less than t.

It is guaranteed that there is an odd number of strings lexicographically not less than s and not greater than t.

Output
Print one string consisting exactly of k lowercase Latin letters — the median (the middle element) of list of strings of length k lexicographically not less than s and not greater than t.

思路:

题意给出字典序最小的字符串和最大的字符串,要求输出字典序中间的字符串,比如,给出字符串aa,ac,中间的字符串为ab。
实际上是一个26进制求平均值的问题,注意对应位置字符相加时会爆char类型。。。

#include <iostream>
#include <algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
#define INF 0x3f3f3f3f
using namespace std;
char a[200005], b[200005];
int ans[200005];
int main()
{
	int k;
	scanf("%d", &k);
	scanf("%s", a);
	scanf("%s", b);
	for (int i = 0; i < k; i++)
	{
		if ((a[i] + b[i]) % 2 == 1)
		{
			ans[i + 1] += 13;
		}
		ans[i] += (a[i] + b[i]) / 2;
		if (ans[i] > 'z')
		{
			ans[i] -= 26;
			int j = i-1;
			while (ans[j] + 1 > 'z')
			{
				ans[j] -= 25;
				j--;
			}
			ans[j] += 1;
		}
	}
	for (int i = 0; i < k; i++)
		printf("%c", ans[i]);
	printf("\n");
}

F.Graph Without Long Directed Paths


题目:

You are given a connected undirected graph consisting of n vertices and m edges. There are no self-loops or multiple edges in the given graph.

You have to direct its edges in such a way that the obtained directed graph does not contain any paths of length two or greater (where the length of path is denoted as the number of traversed edges).

Input
The first line contains two integer numbers n and m (2≤n≤2⋅105, n−1≤m≤2⋅105) — the number of vertices and edges, respectively.

The following m lines contain edges: edge i is given as a pair of vertices ui, vi (1≤ui,vi≤n, ui≠vi). There are no multiple edges in the given graph, i. e. for each pair (ui,vi) there are no other pairs (ui,vi) and (vi,ui) in the list of edges. It is also guaranteed that the given graph is connected (there is a path between any pair of vertex in the given graph).

Output
If it is impossible to direct edges of the given graph in such a way that the obtained directed graph does not contain paths of length at least two, print "NO" in the first line.

Otherwise print "YES" in the first line, and then print any suitable orientation of edges: a binary string (the string consisting only of '0' and '1') of length m. The i-th element of this string should be '0' if the i-th edge of the graph should be directed from ui to vi, and '1' otherwise. Edges are numbered in the order they are given in the input.

思路:

题意要求不能有路径超过2的点,也就是相邻点的颜色不能一样,dfs染色,遇到有环判断首尾颜色是否一致即可。
写的时候过余沙雕,首先dfs中直接return false,然后开的边数和点数一样。。。太菜了

#include <iostream>
#include <algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<map>
using namespace std;
int head[200005];
int a[200005], b[200005];
struct key
{
	int nxt, to;
}e[500005];
int k = 1, n, m;
void build(int a, int b)
{
	e[k].to = b;
	e[k].nxt = head[a];
	head[a] = k++;
	return;
}
int ans[200005];
int vis[200005];
int color[200005];
bool flag=true;
void dfs(int s, int col)
{
	for (int i = head[s]; i != -1; i = e[i].nxt)
	{
		int t = e[i].to;
		if (vis[t] == 1)
		{
			if (color[t] != col)
			{
				flag = false;
				return;
			}
			continue;
		}
		vis[t] = 1;
		color[t] = col;
		dfs(t, -col);
	}
}
int main()
{
	memset(head, -1, sizeof head);
	scanf("%d%d", &n, &m);
	for (int i = 0; i < m; i++)
	{
		scanf("%d%d", &a[i], &b[i]);
		build(a[i], b[i]);
		build(b[i], a[i]);
	}
	vis[1] = 1;
	color[1] = -1;
	dfs(1, 1);
	if (!flag)
	{
		printf("NO\n");
		return 0;
	}
	printf("YES\n");
	for (int i = 0; i < m; i++)
	{
		if (color[a[i]] == 1 && color[b[i]] == -1)
			printf("0");
		else
			printf("1");
	}
	printf("\n");
}

G.Two Merged Sequences


题目:

Two integer sequences existed initially, one of them was strictly increasing, and another one — strictly decreasing.

Strictly increasing sequence is a sequence of integers [x1<x2<⋯<xk]. And strictly decreasing sequence is a sequence of integers [y1>y2>⋯>yl]. Note that the empty sequence and the sequence consisting of one element can be considered as increasing or decreasing.

Elements of increasing sequence were inserted between elements of the decreasing one (and, possibly, before its first element and after its last element) without changing the order. For example, sequences [1,3,4] and [10,4,2] can produce the following resulting sequences: [10,1,3,4,2,4], [1,3,4,10,4,2]. The following sequence cannot be the result of these insertions: [1,10,4,4,3,2] because the order of elements in the increasing sequence was changed.

Let the obtained sequence be a. This sequence a is given in the input. Your task is to find any two suitable initial sequences. One of them should be strictly increasing, and another one — strictly decreasing. Note that the empty sequence and the sequence consisting of one element can be considered as increasing or decreasing.

If there is a contradiction in the input and it is impossible to split the given sequence a into one increasing sequence and one decreasing sequence, print "NO".

Input
The first line of the input contains one integer n (1≤n≤2⋅105) — the number of elements in a.

The second line of the input contains n integers a1,a2,…,an (0≤ai≤2⋅105), where ai is the i-th element of a.

Output
If there is a contradiction in the input and it is impossible to split the given sequence a into one increasing sequence and one decreasing sequence, print "NO" in the first line.

Otherwise print "YES" in the first line. In the second line, print a sequence of n integers res1,res2,…,resn, where resi should be either 0 or 1 for each i from 1 to n. The i-th element of this sequence should be 0 if the i-th element of a belongs to the increasing sequence, and 1 otherwise. Note that the empty sequence and the sequence consisting of one element can be considered as increasing or decreasing.

思路:

题意给出一个数组,将其拆分为严格递增数组,和严格递减数组,和c题不一样的是它必须保留原数组顺序。
给出大佬思路。。。
对于同时可加入递增或递减数组的x,如果x的下一个数y,y>x,就将x加入递增数组,不然就加入递减数组。
tql %%%

#include <iostream>
#include <algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<stack>
#define INF 0x3f3f3f3f
using namespace std;
int n;
int a[200005];
int ans[200005];
int up, down;
int main()
{
	scanf("%d", &n);
	up = -1, down = 300000;
	for (int i =0; i < n; i++)
	{
		scanf("%d", &a[i]);
	}
	int flag = 0;
	for (int i = 0; i < n-1; i++)
	{
		if (a[i] > up&&a[i] < down)
		{
			if (a[i + 1] > a[i])
			{
				ans[i] = 0;
				up = a[i];
			}
			else
			{
				ans[i] = 1;
				down = a[i];
			}
		}
		else if (a[i] > up&&a[i] >= down)
		{
			ans[i] = 0;
			up = a[i];
		}
		else if (a[i] < down&&a[i] <= up)
		{
			ans[i] = 1;
			down = a[i];
		}
		else
		{
			flag = 1;
			break;
		}
	}
	if (a[n - 1]<=up&&a[n - 1]>=down)
		flag = 1;
	else if (a[n - 1] > up)
		ans[n - 1] = 0;
	else ans[n - 1] = 1;
	if (flag == 1)
	{
		printf("NO\n");
		return 0;
	}
	printf("YES\n");
	for (int i = 0; i < n; i++)
	{
		printf("%d", ans[i]);
		if (i != n - 1)printf(" ");
	}
	printf("\n");
}
posted @ 2019-04-09 16:51  booiris  阅读(193)  评论(0编辑  收藏  举报