Codeforces Round #530 (Div. 2)[A,B,C,D]

A. Snowball

Today’s morning was exceptionally snowy. Meshanya decided to go outside and noticed a huge snowball rolling down the mountain! Luckily, there are two stones on that mountain.
Initially, snowball is at height h and it has weight w. Each second the following sequence of events happens: snowball’s weights increases by i, where i — is the current height of snowball, then snowball hits the stone (if it’s present at the current height), then snowball moves one meter down. If the snowball reaches height zero, it stops.
There are exactly two stones on the mountain. First stone has weight u1 and is located at height d1, the second one — u2 and d2 respectively. When the snowball hits either of two stones, it loses weight equal to the weight of that stone. If after this snowball has negative weight, then its weight becomes zero, but the snowball continues moving as before.
Find the weight of the snowball when it stops moving, that is, it reaches height 0.
Input
First line contains two integers w and h — initial weight and height of the snowball (0≤w≤100; 1≤h≤100).
Second line contains two integers u1 and d1 — weight and height of the first stone (0≤u1≤100; 1≤d1≤h).
Third line contains two integers u2 and d2 — weight and heigth of the second stone (0≤u2≤100; 1≤d2≤h; d1≠d2). Notice that stones always have different heights.
Output
Output a single integer — final weight of the snowball after it reaches height 0.

题意:雪球在高度为h的山上往下滚落,过程中会与两块高度分别为d1, d2的石头碰撞,碰撞过程雪球减少与石头相同的重量。开始雪球重量为w,每下落一米雪球都会增加当前高度的重量,当雪球与石头碰撞时重量小于石头时,雪球质量会变为0后继续往下滚动,求雪球在高度为0时的重量是多少?
题解:水题,直接模拟一遍。
code:

#include<iostream>
#include<cstdio>
using namespace std;
int main(){
	int w, h, u1, d1, u2, d2;
	scanf("%d%d%d%d%d%d", &w, &h, &u1, &d1, &u2, &d2);
	for(int i = h; i > 0; i--){
		w+=i;
		if(i==d1) w-=u1;
		else if(i==d2) w-=u2;
		if(w<0){
			w = 0;
		}
	}
	printf("%d\n", w);
	return 0;
} 

B. Squares and Segments

Little Sofia is in fourth grade. Today in the geometry lesson she learned about segments and squares. On the way home, she decided to draw n squares in the snow with a side length of 1. For simplicity, we assume that Sofia lives on a plane and can draw only segments of length 1, parallel to the coordinate axes, with vertices at integer points.
In order to draw a segment, Sofia proceeds as follows. If she wants to draw a vertical segment with the coordinates of the ends (x,y) and (x,y+1). Then Sofia looks if there is already a drawn segment with the coordinates of the ends (x′,y) and (x′,y+1) for some x′. If such a segment exists, then Sofia quickly draws a new segment, using the old one as a guideline. If there is no such segment, then Sofia has to take a ruler and measure a new segment for a long time. Same thing happens when Sofia wants to draw a horizontal segment, but only now she checks for the existence of a segment with the same coordinates x, x+1 and the differing coordinate y.
Sofia is in a hurry, so she wants to minimize the number of segments that she will have to draw with a ruler without a guide. Help her find this minimum number.
Input
The only line of input contains a single integer n (1≤n≤10^9), the number of squares that Sofia wants to draw.
Output
Print single integer, the minimum number of segments that Sofia will have to draw with a ruler without a guide in order to draw n squares in the manner described above.

code:

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int main(){
	int n;
	scanf("%d", &n);
	for(int i = 1; i <= n; i++){
		for(int j = 1; j <= i; j++){
			if(i*j>=n){
				printf("%d\n", i+j);
				return 0;
			}
		}
	}
	return 0;
} 

C. Postcard

Andrey received a postcard from Irina. It contained only the words “Hello, Andrey!”, and a strange string consisting of lowercase Latin letters, snowflakes and candy canes. Andrey thought that this string is an encrypted message, and decided to decrypt it.
Andrey noticed that snowflakes and candy canes always stand after the letters, so he supposed that the message was encrypted as follows. Candy cane means that the letter before it can be removed, or can be left. A snowflake means that the letter before it can be removed, left, or repeated several times.
Andrey knows that messages from Irina usually have a length of k letters. Help him to find out if a given string can encode a message of k letters, and if so, give an example of such a message.
For example, consider the following string: hw?ap*yn?eww*ye*ar
This string can encode the message «happynewyear». For this, candy canes and snowflakes should be used as follows:

  • candy cane 1: remove the letter w,
  • snowflake 1: repeat the letter p twice,
  • candy cane 2: leave the letter n,
  • snowflake 2: remove the letter w,
  • snowflake 3: leave the letter e.

题意:Andrey有一串密码串仅包含小写字母与‘ * ’,‘?’,‘ * ’表示前面的小写字母可以被删除、保留或者重复任意次;‘ ?’表示前面的小写字母可以被保留或者删除,并且满足两个特殊符号前面必然为小写字母。问密码串能否被解析成只有k个字符的字符串(只包含小写字母)
题解:可以分成四种情况讨论,我们设当前密码串中小写字母的数量为up:

  • 当up < k时,表示解析出来的字符串比当前密码串中的小写字母多。
    • 若当前密码串不存在‘ * ’,则无解,输出‘Impossible’
    • 若当前密码串存在‘ * ’,则可以解析。在第一个出现 ’ * '的位置重复(k-up)个小写字母,其他特殊符号去掉即可。
  • 当up >= k时,表示解析出来的字符串比当前密码串中的小写字母少。
    • 若当前密码串特殊符号总数<(k-up),则无解。输出‘Impossible’
    • 若当前密码串特殊符号总数>(k-up),则可以解析。将前(k-up)个特殊符号前面的小写字母去掉其余保留即可。

code:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int main(){
	char s[210];
	int k;
	scanf("%s%d", s, &k);
	int up = 0, t1 = 0, t2 = 0, len = strlen(s);
	for(int i = 0; i < len; i++){
		if('a' <= s[i] && s[i] <= 'z') up++;
		else if(s[i] == '?') t1++;
		else t2++;
	} 
	if(k <= up){
		int f = up-k;
		if(f > t1+t2) printf("Impossible\n");
		else{
			for(int i = 0; i < len; i++){
				if((i+1!=len && (s[i+1]=='?' || s[i+1]=='*') && f > 0)){
					f--;
					continue;
				}
				else if(s[i]=='?' || s[i]=='*') continue;
				printf("%c", s[i]);
			}
		}
	}
	else{
		if(!t2) printf("Impossible\n");
		else{
			bool flag = true;
			int f = k-up;
			for(int i = 0; i < len; i++){
				if(i+1!=len && s[i+1]=='*' && flag == true){
					for(int j = 0; j <= f; j++) printf("%c", s[i]);
					flag = false;
					continue;
				}
				else if(s[i]=='?' || s[i]=='*') continue;
				printf("%c", s[i]);
			}
		}
	}
	return 0;
} 

D. Sum in the tree

Mitya has a rooted tree with n vertices indexed from 1 to n, where the root has index 1. Each vertex v initially had an integer number av≥0 written on it. For every vertex v Mitya has computed sv: the sum of all values written on the vertices on the path from vertex v to the root, as well as hv — the depth of vertex v, which denotes the number of vertices on the path from vertex v to the root. Clearly, s1=a1 and h1=1.
Then Mitya erased all numbers av, and by accident he also erased all values sv for vertices with even depth (vertices with even hv). Your task is to restore the values av for every vertex, or determine that Mitya made a mistake. In case there are multiple ways to restore the values, you’re required to find one which minimizes the total sum of values av for all vertices in the tree.
Input
The first line contains one integer n — the number of vertices in the tree (2≤n≤1e5). The following line contains integers p2, p3, … pn, where pi stands for the parent of vertex with index i in the tree (1≤pi<i). The last line contains integer values s1, s2, …, sn (−1≤sv≤1e9), where erased values are replaced by −1.
Output
Output one integer — the minimum total sum of all values av in the original tree, or −1 if such tree does not exist.

题意:有一颗树每一个顶点都存在av,sv,hv值。

  • av:顶点权值
  • sv:顶点到根节点av的总和
  • hv:顶点的深度

规定顶点1为根结点且其深度为1。Mitya将树的av值全部抹去,还有深度为偶数的所有sv值抹去。问树所有顶点av值总和最小是多少?
题解:对数据建边,DFS从顶点1开始找其孩子顶点。
则顶点深度为偶数的sv值为其所有孩子顶点中与其父顶点sv的差的最小值加上父顶点的sv值。
最后枚举一遍对每一个顶点的av(sv-su)求和。注意使用Long long!!!
code:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 1e5+10;
const long long INF = 0x3f3f3f3f3f3f3f3f;
int tree[maxn];
long long w[maxn];
struct Edge{
	int v, next;
}edge[maxn];
int head[maxn], cnt;
void init(){
	cnt = 0;
	memset(head, -1, sizeof(head));
}
void addEdge(int u, int v){
	edge[cnt].v = v;
	edge[cnt].next = head[u];
	head[u] = cnt++;
}
void dfs(int idx, int now, int u){
	if(now){
		for(int i = head[idx]; i != -1; i = edge[i].next){
			int v = edge[i].v;
			dfs(v, now^1, idx);
		}
	}
	else{
		long long Min = INF;
		for(int i = head[idx]; i != -1; i = edge[i].next){
			int v = edge[i].v;
			Min = min(Min, w[v]-w[u]);
			dfs(v, now^1, idx);
		}
		w[idx] = Min!=INF?Min+w[u]:0+w[u];
	}
}
int main(){
	init();
	int n;
	tree[1] = 0;
	scanf("%d", &n);
	for(int i = 2; i <= n; i++){
		scanf("%d", &tree[i]);
		addEdge(tree[i], i);
	}
	for(int i = 1; i <= n; i++){
		scanf("%lld", &w[i]);
	}
	
	dfs(1, 1, -1);
	long long ans = 0;
	for(int i = 1; i <= n; i++){
		ans+=w[i]-w[tree[i]];
		if(w[i]-w[tree[i]]<0){
			printf("-1\n");
			return 0;
		}
	}
	printf("%lld\n", ans);
	return 0;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章