[2.9训练]【CF909C】Python Indentation,【CF909D】Colorful Points,【CF909E】Coprocessor


在这里插入图片描述

T1:Python Indentation

题目

题目描述
In Python, code blocks don’t have explicit begin/end or curly braces to mark beginning and end of the block. Instead, code blocks are defined by indentation.

We will consider an extremely simplified subset of Python with only two types of statements.

Simple statements are written in a single line, one per line. An example of a simple statement is assignment.

For statements are compound statements: they contain one or several other statements. For statement consists of a header written in a separate line which starts with “for” prefix, and loop body. Loop body is a block of statements indented one level further than the header of the loop. Loop body can contain both types of statements. Loop body can’t be empty.

You are given a sequence of statements without indentation. Find the number of ways in which the statements can be indented to form a valid Python program.

输入格式
The first line contains a single integer N ( 1<=N<=5000) — the number of commands in the program. N lines of the program follow, each line describing a single command. Each command is either “f” (denoting “for statement”) or “s” (“simple statement”). It is guaranteed that the last line is a simple statement.

输出格式
Output one line containing an integer - the number of ways the given sequence of statements can be indented modulo 1 0 9 + 7 10^{9}+7

题意翻译
CF909C Python的缩进 Python的代码中不需要写begin、end或者大括号去标记开头或结尾。 我们将考虑一种Python非常简化的子集,它的语句只有两种类型。 每行只写一个简单语句,比如赋值。 For语句是一个较复杂的语句,他们可能包含一个或多个其他的语句。 For语句由一个单独的行组成,以“For”前缀和循环体开头。 循环体是一个语句块,比循环头缩进一级。 循环体可以包含这两种类型的语句。循环体不能为空。 给你一个没有缩进的序列,求有多少种方式添加缩进可以形成一个完整的Python代码。 输入格式: 第一行:N 接下来N行每行一个字符f(for语句)或s(简单语句)。 保证最后一行一定是s(简单语句)。 输出格式: 输出方案数,答案对10^9+7取模。

输入输出样例
输入
4
s
f
f
s
输出
1

输入
4
f
s
f
s
输出
2

题解

d p [ i ] [ j ] dp[i][j] 表示第 i i 条语句在第 j j 层循环

接着该条语句如果是 s s 能放在 j j 层,则后一条不管是什么都能放在 1 j 1-j
如果是 f f 那么就可以扩展一层,对后面的语句造成影响
因此我们如果是便输入便处理,一定处理的是前一条语句

d p [ i ] [ j ] dp[i][j] 就有两种情况了
(1):前一条是 s s :放在第 j j 层循环内的所有方案数都可以放在 1 1 j 1 j-1 层,那么就应该将 1 1 j 1 j-1 的方案数都加上这个值
(2):前一条是 f f :扩展一层,即放在第 j j 层循环内的方案数等于放在第 j 1 j-1 层循环内的所有方案数

最后就是发现二维数组MLE,再细想 i i 的状态只跟 i 1 i-1 有关,就可以使用滚动数组
在这里插入图片描述

code

#include <cstdio>
#include <iostream>
using namespace std;
#define MAXN 5005
#define LL long long
const int mod = 1e9 + 7;
int n, cnt, f;
char s, pre;
LL result, dp[MAXN], last[MAXN];

int main() {
	scanf ( "%d", &n );
	dp[1] = 1;
	for ( int i = 1;i <= n;i ++ ) {
		cin >> s;
		if ( pre == 's' ) {
			for ( int j = cnt;j >= 1;j -- )
				dp[j] = ( dp[j + 1] + last[j] ) % mod;	
		}
		else {
			++ cnt;
			for ( int j = cnt;j > 1;j -- )
				dp[j] = last[j - 1];
		}
		for ( int j = 1;j <= cnt;j ++ ) {
			last[j] = dp[j];
			dp[j] = 0;
		}
		pre = s;
	}
	for ( int i = 1;i <= cnt;i ++ )
		result = ( result + last[i] ) % mod;
	printf ( "%lld", result );
	return 0;
} 

T2:Colorful Points

题目

题目描述
You are given a set of points on a straight line. Each point has a color assigned to it. For point a a , its neighbors are the points which don’t have any other points between them and a a . Each point has at most two neighbors - one from the left and one from the right.

You perform a sequence of operations on this set of points. In one operation, you delete all points which have a neighbor point of a different color than the point itself. Points are deleted simultaneously, i.e. first you decide which points have to be deleted and then delete them. After that you can perform the next operation etc. If an operation would not delete any points, you can’t perform it.

How many operations will you need to perform until the next operation does not have any points to delete?

输入格式
Input contains a single string of lowercase English letters ‘a’-‘z’. The letters give the points’ colors in the order in which they are arranged on the line: the first letter gives the color of the leftmost point, the second gives the color of the second point from the left etc.

The number of the points is between 1 and 1 0 6 10^{6}
输出格式
Output one line containing an integer - the number of operations which can be performed on the given set of points until there are no more points to delete.

题意翻译
你将得到一些在同一条线上的点,每一个点都有一种颜色。对于点a,他的邻居是他左边最靠近他的点和他左边最靠近他的点。(每个点最多有两个邻居,左边的和右边的) 你要对这些点做一些操作:每次同时删除颜色与邻居不同的点 。 解词:
同时:不会出现本来a点不用删,但删除a的邻居后,a需要删除,举个例子:
一开始:aabb 第一次后:ab(第二个a和第一个b删掉) 最后: (没了) 现在问你你要执行几次操作后,这些点无法再进行删除。(相当于几次后这些点都删完了或颜色都一样)

输入输出样例
输入
aabb
输出
2

输入
aabcaa
输出
1
说明/提示
In the first test case, the first operation will delete two middle points and leave points “ab”, which will be deleted with the second operation. There will be no points left to apply the third operation to.

In the second test case, the first operation will delete the four points in the middle, leaving points “aa”. None of them have neighbors of other colors, so the second operation can’t be applied.

题解

其实就是一道模拟题
既然只有不相同的相邻字母才会一起消失,
我们就容易联想到强连通分量里面的缩点的感觉
在这里,我们把连续相同的一段字母锁在一起
然后原数组就被我们变成了两两之间不相同的
每一个区域都要跟左右抵消 2 -2 ,首尾特殊的 1 -1
然后再重新锁字母就可以了
在这里插入图片描述

code

#include <cstdio>
#include <cstring>
using namespace std;
#define MAXN 1000005
struct node {
	char c;
	int num;
	node () {}
	node ( char C, int Num ) {
		c = C;
		num = Num;
	}
}f[MAXN];
char s[MAXN];
int tot, result;

void press () {
	int len = tot;
	tot = 0;
	for ( int i = 1;i <= len;i ++ )
		if ( f[i].num > 0 ) {//后面的-1/2可能减成负的
			if ( f[i].c == f[tot].c )
				f[tot].num += f[i].num;
			else
				f[++ tot] = f[i];
		}
} 

int main() {
	scanf ( "%s", s );
	int len = strlen ( s );
	for ( int i = 1;i <= len;i ++ ) {
		f[i].c = s[i - 1];
		f[i].num = 1;
	}
	tot = len;
	press ();
	while ( tot > 1 ) {
		result ++;
		for ( int i = 2;i < tot;i ++ )
			f[i].num -= 2;
		f[1].num --;
		f[tot].num --;
		press ();
	}
	printf ( "%d", result );
	return 0;
}

T3:Coprocessor

题目

题目描述
You are given a program you want to execute as a set of tasks organized in a dependency graph. The dependency graph is a directed acyclic graph: each task can depend on results of one or several other tasks, and there are no directed circular dependencies between tasks. A task can only be executed if all tasks it depends on have already completed.

Some of the tasks in the graph can only be executed on a coprocessor, and the rest can only be executed on the main processor. In one coprocessor call you can send it a set of tasks which can only be executed on it. For each task of the set, all tasks on which it depends must be either already completed or be included in the set. The main processor starts the program execution and gets the results of tasks executed on the coprocessor automatically.

Find the minimal number of coprocessor calls which are necessary to execute the given program.

输入格式
The first line contains two space-separated integers N ( 1 < = N < = 1 0 5 1<=N<=10^5 ) — the total number of tasks given, and M ( 0 < = M < = 1 0 5 0<=M<=10^5 ) — the total number of dependencies between tasks.

The next line contains N space-separated integers . If Ei=0 , task i can only be executed on the main processor, otherwise it can only be executed on the coprocessor.

The next M lines describe the dependencies between tasks. Each line contains two space-separated integers T1 and T2 and means that task T1depends on task T2 (T1≠T2). Tasks are indexed from 0 to N−1 . All M pairs (T1,T2)are distinct. It is guaranteed that there are no circular dependencies between tasks.

输出格式
Output one line containing an integer — the minimal number of coprocessor calls necessary to execute the program.

题意翻译
给你一堆任务,有些要用主处理器处理,有些要用副处理器处理,副处理器可以一次处理很多个任务,一个任务能被执行的条件为前继任务已经被执行过了或者前继任务和自己同时被放进副处理器处理,现在给你这些前继任务的关系和每个任务处理要用的处理器,求副处理器最少运行了几次,保证关系是一张有向无环图

输入输出样例
输入
4 3
0 1 0 1
0 1
1 2
2 3
输出
2

输入
4 3
1 1 1 0
0 1
0 2
3 0
输出
1
说明/提示
In the first test, tasks 1 and 3 can only be executed on the coprocessor. The dependency graph is linear, so the tasks must be executed in order 3 -> 2 -> 1 -> 0. You have to call coprocessor twice: first you call it for task 3, then you execute task 2 on the main processor, then you call it for for task 1, and finally you execute task 0 on the main processor.

In the second test, tasks 0, 1 and 2 can only be executed on the coprocessor. Tasks 1 and 2 have no dependencies, and task 0 depends on tasks 1 and 2, so all three tasks 0, 1 and 2 can be sent in one coprocessor call. After that task 3 is executed on the main processor.

题解

在这里插入图片描述
都想得到的贪心就是先把所有能再主机上做的一次性全都做了,这样在辅机上的才能尽可能地一锅端
这里因为可以前继任务和自己同时被放进副处理器处理就把我之前的纯bfs拍死了

这种要前面所有任务都完成才能进行下一步的明显就是拓扑排序的模型
将主机和辅机分开做,先把主机端完,再康康辅机里面是否有任务再端辅机

最后要保证每个任务都被处理了就行

code

#include <queue>
#include <cstdio>
#include <vector>
#include <iostream>
using namespace std;
#define MAXN 100005
queue < int > Qmain, Qco;
vector < int > G[MAXN];
int n, m, T1, T2, result;
bool vis[MAXN];
int E[MAXN], d[MAXN];

int main() {
	scanf ( "%d %d", &n, &m );
	for ( int i = 0;i < n;i ++ )
		scanf ( "%d", &E[i] );
	for ( int i = 1;i <= m;i ++ ) {
		scanf ( "%d %d", &T1, &T2 );
		G[T2].push_back ( T1 );
		d[T1] ++;
	}
	for ( int i = 0;i < n;i ++ )
		if ( ! d[i] )
			if ( E[i] )
				Qco.push ( i );
			else
				Qmain.push ( i );
	while ( ( ! Qmain.empty() ) || ( ! Qco.empty() ) ) {
		while ( ! Qmain.empty() ) {
			int t = Qmain.front();
			Qmain.pop();
			vis[t] = 1;
			for ( int i = 0;i < G[t].size();i ++ ) {
				int v = G[t][i];
				if ( vis[v] ) 
					continue;
				d[v] --;
				if ( d[v] )
					continue;
				if ( E[v] )
					Qco.push ( v );
				else
					Qmain.push ( v );
			}
		}
		if ( ! Qco.empty() ) {
			result ++;
			while ( ! Qco.empty() ) {
				int t = Qco.front();
				Qco.pop();
				vis[t] = 1;
				for ( int i = 0;i < G[t].size();i ++ ) {
					int v = G[t][i];
					if ( vis[v] ) 
						continue;
					d[v] --;
					if ( d[v] )
						continue;
					if ( E[v] )
						Qco.push ( v );
					else
						Qmain.push ( v );
				}
			}
		}
	}
	printf ( "%d", result );
	return 0;
}

感觉今天的题解怎么这么水了

猜你喜欢

转载自blog.csdn.net/Emm_Titan/article/details/104235711