SDNU_ACM_ICPC_2019_Winter_Practice_3rd

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chenshibo17/article/details/86677820

A - Replace To Make Regular Bracket Sequence

You are given string s consists of opening and closing brackets of four kinds <>,{}, [], (). There are two types of brackets: opening and closing. You can replace any bracket by another of the same type. For example, you can replace < by the bracket {, but you can't replace it by ) or >.

The following definition of a regular bracket sequence is well-known, so you can be familiar with it.

Let's define a regular bracket sequence (RBS). Empty string is RBS. Let s1 and s2 be a RBS then the strings <s1>s2, {s1}s2, [s1]s2, (s1)s2 are also RBS.

For example the string "[[(){}]<>]" is RBS, but the strings "[)()" and "][()()" are not.

Determine the least number of replaces to make the string s RBS.

Input

The only line contains a non empty string s, consisting of only opening and closing brackets of four kinds. The length of s does not exceed 106.

Output

If it's impossible to get RBS from s print Impossible.

Otherwise print the least number of replaces needed to get RBS from s.

Examples

Input

[<}){}

Output

2

Input

{()}[]

Output

0

Input

]]

Output

Impossible

         四种左括号四种右括号,左括号之间,右括号之间可以相互转换。假设s是一个好的字符串,那么"(s)",以及"s()"都是好的字符串,请问将整个所给字符串变成哈皮的字符串最小需要几次变换~~如果转换不了输出“impossible”;

         这道题的话,我自己使用栈来做,对于题目要求来说我们可以理解成每一个类型的左括号必须与一个相同类型的右括号相匹配这个要求(左边一个‘[’,字符串的右边必须有一个专属于他的‘]’相对应),这样的话栈就相当于等待配对的左括号,然后进行下一次次的向右匹配。

#include<bits/stdc++.h>
using namespace std;
bool finz(char x) {//判断是否为左括号
	if (x == '[' || x == '{' || x == '(' || x == '<')
		return 1;
	return 0;
}
bool fuck(int a, int b) {//判断是否是相匹配
	if (a == '('&&b == ')')
		return 1;
	if (a == '<'&&b == '>')
		return 1;
	if (a == '{'&&b == '}')
		return 1;
	if (a == '['&&b == ']')
		return 1;
	return 0;
}
int main() {
	string m;
	cin >> m;
	int len = m.length();
	stack<char>q;
	int ans = 0;
	for (int i = 0; i < len; i++) {
		if (finz(m[i])) {
			q.push(m[i]);
		}
		else {
			if (q.empty()) {//此时如果有一个想匹配的右括号但是已经没有左括号了,就说明错了
				cout << "Impossible" << endl;
				return 0;
			}
			else {
				char t = q.top();
				q.pop();
				if (!fuck(t, m[i])) {
					ans++;
				}
			}
		}
	}
	if (q.size()) {//此时如果有想匹配的左括号但是已经没有右括号了
		cout << "Impossible" << endl;
		return 0;
	}
	else {
		cout << ans << endl;
	}
	return 0;
}

B - Pearls in a Row

There are n pearls in a row. Let's enumerate them with integers from 1 to n from the left to the right. The pearl number i has the type ai.

Let's call a sequence of consecutive pearls a segment. Let's call a segment good if it contains two pearls of the same type.

Split the row of the pearls to the maximal number of good segments. Note that each pearl should appear in exactly one segment of the partition.

As input/output can reach huge size it is recommended to use fast input/output methods: for example, prefer to use scanf/printf instead of cin/cout in C++, prefer to use BufferedReader/PrintWriter instead of Scanner/System.out in Java.

Input

The first line contains integer n (1 ≤ n ≤ 3·105) — the number of pearls in a row.

The second line contains n integers ai (1 ≤ ai ≤ 109) – the type of the i-th pearl.

Output

On the first line print integer k — the maximal number of segments in a partition of the row.

Each of the next k lines should contain two integers lj, rj (1 ≤ lj ≤ rj ≤ n) — the number of the leftmost and the rightmost pearls in the j-th segment.

Note you should print the correct partition of the row of the pearls, so each pearl should be in exactly one segment and all segments should contain two pearls of the same type.

If there are several optimal solutions print any of them. You can print the segments in any order.

If there are no correct partitions of the row print the number "-1".

Examples

Input

5
1 2 3 4 1

Output

1
1 5

Input

5
1 2 3 4 5

Output

-1

Input

7
1 2 1 3 1 2 1

Output

2
1 3
4 7

    每个位置有一个值,当某一个片段有两个相同的值得时候,他就是好的。。请问最多分成几个好的片段。

    那就找呗。。设个set用来保存之前得已经出现过的值,如果再次出现那就说明此时已经可以成为一个好片断了,立刻提出来就好。(就是希望用越少的量形成好片段)

#include<bits/stdc++.h>
using namespace std;
int m[300005];
int main() {
	int n;
	ios::sync_with_stdio(0);
	while (cin >> n) {
		for (int i = 1; i <= n; i++)
			cin >> m[i];
		int ans = 0, last = 1;
		set<int>G; queue<int>ans1, ans2;
		for (int i = 1; i <= n; i++) {
			if (G.find(m[i]) != G.end()) {
				ans1.push(last);
				ans2.push(i);
				last = i + 1;
				G.clear();
			}
			else {
				G.insert(m[i]);
			}
		}
		if (ans1.size() == 0) {
			cout << -1 << endl;
			continue;
		}
		cout << ans1.size() << endl;
		while (!ans1.empty()) {
			int a = ans1.front(), b = ans2.front();
			ans1.pop(); ans2.pop();
			if (ans1.empty())//别忘了这里,假设最后剩下的那一段不能形成好片段,就把这个并入之前得好片段里去
				b = n;
			cout << a << " " << b << endl;
		}
	}
	return 0;
}

C - 排列2

Ray又对数字的列产生了兴趣: 
现有四张卡片,用这四张卡片能排列出很多不同的4位数,要求按从小到大的顺序输出这些4位数。 

Input

每组数据占一行,代表四张卡片上的数字(0<=数字<=9),如果四张卡片都是0,则输入结束。 

Output

对每组卡片按从小到大的顺序输出所有能由这四张卡片组成的4位数,千位数字相同的在同一行,同一行中每个四位数间用空格分隔。 
每组输出数据间空一行,最后一组数据后面没有空行。 

Sample Input

1 2 3 4
1 1 2 3
0 1 2 3
0 0 0 0

Sample Output

1234 1243 1324 1342 1423 1432
2134 2143 2314 2341 2413 2431
3124 3142 3214 3241 3412 3421
4123 4132 4213 4231 4312 4321

1123 1132 1213 1231 1312 1321
2113 2131 2311
3112 3121 3211

1023 1032 1203 1230 1302 1320
2013 2031 2103 2130 2301 2310
3012 3021 3102 3120 3201 3210

       emmm这道题其实就是输出格式烦人。。处理好这个就行了。

#include<bits/stdc++.h>
using namespace std;
set<int>ans;
void fun3(int sum,int a) {
	sum += a;
	ans.insert(sum);
}
void fun2(int sum, int a, int b) {
	fun3(sum + a * 10, b);
	fun3(sum + b * 10, a);
}
void fun1(int a, int b, int c) {
	ans.clear();
	fun2(a * 100, b, c);
	fun2(b * 100, a, c);
	fun2(c * 100, b, a);
}
void solve(int a, int b, int c, int d) {
	if (a != 0) {
		fun1(b, c, d);
		set<int>::iterator it;
		for (it = ans.begin(); it != ans.end(); it++) {
			set<int>::iterator itor = it;
			itor++;
			if (itor == ans.end()) {
				cout << a*1000+*it << endl;
			}
			else {
				cout << a*1000+*it << " ";
			}
		}
	}
}
int main() {
	ios::sync_with_stdio(0);
	int a, b, c, d;
	int spot = 0;
	while (cin >> a >> b >> c >> d) {
		if (a + b + c + d == 0) 
			break;
		if (spot)cout << endl;
		spot = 1;
		int m[5]; bool spot[5];
		memset(spot, 0, sizeof spot);	
		m[1] = a; m[2] = b; m[3] = c; m[4] = d;
		sort(m + 1, m + 5);
		for (int i = 2; i <= 4; i++) {//处理相同的千位不能重复输出
			if (m[i] == m[i - 1]) {
				spot[i] = 1;
			}
		}
		sort(m + 1, m + 5);
		if(!spot[1])
			solve(m[1], m[2], m[3], m[4]);
		if (!spot[2])
			solve(m[2], m[1], m[3], m[4]);
		if (!spot[3])
			solve(m[3], m[2], m[1], m[4]);
		if (!spot[4])
			solve(m[4], m[2], m[3], m[1]);
	}
	return 0;
}

D - Can you find it?

Give you three sequences of numbers A, B, C, then we give you a number X. Now you need to calculate if you can find the three numbers Ai, Bj, Ck, which satisfy the formula Ai+Bj+Ck = X. 

Input

There are many cases. Every data case is described as followed: In the first line there are three integers L, N, M, in the second line there are L integers represent the sequence A, in the third line there are N integers represent the sequences B, in the forth line there are M integers represent the sequence C. In the fifth line there is an integer S represents there are S integers X to be calculated. 1<=L, N, M<=500, 1<=S<=1000. all the integers are 32-integers. 

Output

For each case, firstly you have to print the case number as the form "Case d:", then for the S queries, you calculate if the formula can be satisfied or not. If satisfied, you print "YES", otherwise print "NO". 

Sample Input

3 3 3
1 2 3
1 2 3
1 2 3
3
1
4
10

Sample Output

Case 1:
NO
YES
NO

        给一个n,然后输入a得取值得可能值,b取值得可能值,c取值得可能值,在输入num个数,问能不能在这些区间里取值来取到所给得num个数。

        对于每一个所给数,首先我们把所有a+b得可能情况存起来(ans1中),然后遍历这个数组,则如果我们想得到a+b+c=所给数得话,对于每一个ans1[i](代表a+b),我们所要的就是(所给数-ans1[i])看看c中存不存在。话说lower_bound和upper_bound是两个非常好用的二分函数,你们可以自己去搜一下去学学。

#include<bits/stdc++.h>
using namespace std;
int ans1[250005];
int n[505], m[505], z[505];
int a, b, c;
int main() {
	ios::sync_with_stdio(0);
	//int a, b, c;
	int te = 1;
	while (cin >> a >> b >> c) {
		cout << "Case " << te << ":" << endl;
		te++;
		for (int i = 0; i < a; i++) 
			cin >> n[i];
		for (int i = 0; i < b; i++)
			cin >> m[i];
		for (int i = 0; i < c; i++)
			cin >> z[i];
		int cnt = 0;
		for (int i = 0; i < a; i++) {
			for (int j = 0; j < b; j++) {
				ans1[cnt++] = n[i] + m[j];
			}
		}
		sort(ans1, ans1 + a*b);
		int sum;
		cin >> sum;
		while (sum--) {
			int t, spot = 0;
			cin >> t;
			for (int i = 0; i < c; i++) {
				int need = t - z[i];
				int pos1 = lower_bound(ans1, ans1 + a*b, need) - ans1;
				int pos2 = upper_bound(ans1, ans1 + a*b, need) - ans1;
				if (pos2 - pos1 > 0) {
					spot = 1; break;
				}
			}
			if (spot)
				cout << "YES" << endl;
			else
				cout << "NO" << endl;
		}
	}
	return 0;
}

E - Legal or Not

ACM-DIY is a large QQ group where many excellent acmers get together. It is so harmonious that just like a big family. Every day,many "holy cows" like HH, hh, AC, ZT, lcc, BF, Qinz and so on chat on-line to exchange their ideas. When someone has questions, many warm-hearted cows like Lost will come to help. Then the one being helped will call Lost "master", and Lost will have a nice "prentice". By and by, there are many pairs of "master and prentice". But then problem occurs: there are too many masters and too many prentices, how can we know whether it is legal or not?

We all know a master can have many prentices and a prentice may have a lot of masters too, it's legal. Nevertheless,some cows are not so honest, they hold illegal relationship. Take HH and 3xian for instant, HH is 3xian's master and, at the same time, 3xian is HH's master,which is quite illegal! To avoid this,please help us to judge whether their relationship is legal or not. 

Please note that the "master and prentice" relation is transitive. It means that if A is B's master ans B is C's master, then A is C's master.

Input

The input consists of several test cases. For each case, the first line contains two integers, N (members to be tested) and M (relationships to be tested)(2 <= N, M <= 100). Then M lines follow, each contains a pair of (x, y) which means x is y's master and y is x's prentice. The input is terminated by N = 0. 
TO MAKE IT SIMPLE, we give every one a number (0, 1, 2,..., N-1). We use their numbers instead of their names.

Output

For each test case, print in one line the judgement of the messy relationship. 
If it is legal, output "YES", otherwise "NO".

Sample Input

3 2
0 1
1 2
2 2
0 1
1 0
0 0

Sample Output

YES
NO

       其实这道题意义就是判断是否有环就是了(a->b,b->c,c->a),我为了省写代码的时间直接复制了之后的H,用拓扑排序检查图是否有环,其实不用这么麻烦,你自己写个floyd暴力跑也是可以的(每个点到自己的距离为0,其他值为inf,然后根据所给得边建负的权值边,跑floyd看最后每个点到自己距离是否也变成负的了。)

#include<bits/stdc++.h>
using namespace std;
int n, m, te, in[105];
vector<int>G[105];
queue<int>q;
bool topo() {
	int t = n;
	while (!q.empty())
		q.pop();
	while (t--) {
		int ret = -1;
		for (int i = 0; i < n; i++) {
			if (in[i] == 0) {
				ret = i; in[i] = -1;
				break;
			}
		}
		if (ret == -1)return 0;
		int sz = G[ret].size();
		q.push(ret);
		for (int i = 0; i < sz; i++) {
			int v = G[ret][i];
			in[v]--;
		}
	}
	return 1;
}
int main() {
	ios::sync_with_stdio(0);
	while (cin >> n >> m&&n + m) {
		memset(in, 0, sizeof in);
		for (int i = 0; i < 105; i++)
			G[i].clear();
		while (m--) {
			int a, b;
			cin >> a >> b;
			in[b]++;
			G[a].push_back(b);
		}
		if (topo()) {
			cout << "YES" << endl;
		}
		else {
			cout << "NO" << endl;
		}
	}
	return 0;
}

 

F - Ignatius and the Princess IV

  

"OK, you are not too bad, em... But you can never pass the next test." feng5166 says. 

"I will tell you an odd number N, and then N integers. There will be a special integer among them, you have to tell me which integer is the special one after I tell you all the integers." feng5166 says. 

"But what is the characteristic of the special integer?" Ignatius asks. 

"The integer will appear at least (N+1)/2 times. If you can't find the right integer, I will kill the Princess, and you will be my dinner, too. Hahahaha....." feng5166 says. 

Can you find the special integer for Ignatius? 

Input

The input contains several test cases. Each test case contains two lines. The first line consists of an odd integer N(1<=N<=999999) which indicate the number of the integers feng5166 will tell our hero. The second line contains the N integers. The input is terminated by the end of file. 

Output

For each test case, you have to output only one line which contains the special number you have found. 

Sample Input

5
1 3 2 3 3
11
1 1 1 1 1 5 5 5 5 5 5
7
1 1 1 1 1 1 1

Sample Output

3
5
1

      有n个值(奇数),求其中出现次数为n/2+1的。

      emmm自我喜欢名叫“打擂台”的方法,每次输入数,看看擂台上有没有数,如果有的且是自己,则擂台上数量加一,不是自己就擂台上数量减一,如果没有数则自己上去,数量为一。

#include<bits/stdc++.h>
using namespace std;
int n, m, te;
int main() {
	ios::sync_with_stdio(0);
	while (cin >> n) {
		int num , sum = 0;
		while (n--) {
			int a; cin >> a;
			if (sum == 0) {
				num = a;
				sum = 1;
			}
			else if (num == a) {
				sum++;
			}
			else{
				sum--;
			}
		}
		cout << num << endl;
	}
	return 0;
}

G - Can you solve this equation?

Now,given the equation 8*x^4 + 7*x^3 + 2*x^2 + 3*x + 6 == Y,can you find its solution between 0 and 100; 
Now please try your lucky.

Input

The first line of the input contains an integer T(1<=T<=100) which means the number of test cases. Then T lines follow, each line has a real number Y (fabs(Y) <= 1e10);

Output

For each test case, you should just output one real number(accurate up to 4 decimal places),which is the solution of the equation,or “No solution!”,if there is no solution for the equation between 0 and 100.

Sample Input

2
100
-4

Sample Output

1.6152
No solution!

       问在0-100的取值范围内内否有一个x值能让fun(x)等于所给的数(小数点后四位)。

       可以看出来这个函数是递增的。。所以是可以用二分进行搜查的。。暴力查询某个值能不能用。。。还有就是所给数如果小于fun(0)或者大于fun(100)是肯定找不到的,反之是肯定找得到的。(递增性质)

#include<bits/stdc++.h>
using namespace std;
int n, te;
double fun(double x) {
	return 8 * x*x*x*x + 7 * x*x*x + 2 * x*x + 3 * x + 6;
}
int main() {
	cin >> te;
	while (te--) {
		int a, t;
		cin >> a;
		t = fun(a);
		if (fun(100) < a || 6 > a) {
			cout << "No solution!" << endl;
			continue;
		}
		double le = 0, ri = 100, ans;
		while (ri - le > 1e-6) {
			double mid = (ri + le) / 2;
			if (fun(mid) >= a) {
				ri = mid;
				ans = ri;
			}
			else {
				le = mid + 0.000001;
			}
		}
		printf("%.4lf\n", ans);
	}
	return 0;
}

H - Ordering Tasks

 John has n tasks to do. Unfortunately, the tasks are not independent and the execution of one task is only possible if other tasks have already been executed.

Input

The input will consist of several instances of the problem. Each instance begins with a line containing two integers, 1 ≤ n ≤ 100 and m. n is the number of tasks (numbered from 1 to n) and m is the number of direct precedence relations between tasks. After this, there will be m lines with two integers i and j, representing the fact that task i must be executed before task j. An instance with n = m = 0 will finish the input.

Output

For each instance, print a line with n integers representing the tasks in a possible order of execution.

Sample Input

5 4

1 2

2 3

1 3

1 5

0 0

Sample Output

1 4 2 5 3

         有一些作业完成之前是需要先完成某一项或几项别的作业的。。求输出任何一组可行的做作业顺序。

         基础topo排序,不会的自学即可(顺便想想如果不是随即一个可行顺序,如果是某个字典序最小?最大的顺序的时候你该怎么操作呢?)。

#include<bits/stdc++.h>
using namespace std;
int n, m, te, in[105];
vector<int>G[105];
queue<int>q;
void topo() {
	int t = n;
	while (!q.empty()) 
		q.pop();
	while (t--) {
		int ret;
		for (int i = 1; i <= n; i++) {
			if (in[i] == 0) {
				ret = i; in[i] = -1;
				break;
			}
		}
		int sz = G[ret].size();
		q.push(ret);
		for (int i = 0; i < sz; i++) {
			int v = G[ret][i];
			in[v]--;
		}
	}
	while (!q.empty()) {
		int r = q.front();
		q.pop();
		if (q.empty()) {
			cout << r << endl;
		}
		else
			cout << r << " ";
	}
}
int main() {
	ios::sync_with_stdio(0);
	while (cin >> n >> m&&n + m) {
		memset(in, 0, sizeof in);
		for (int i = 0; i < 105; i++) 
			G[i].clear();
		while (m--) {
			int a, b;
			cin >> a >> b;
			in[b]++;
			G[a].push_back(b);
		}
		topo();
	}
	return 0;
}

 

I - I Can Guess the Data Structure!

         因为pdf的原因我就不把原题弄上来了。

         大意就是判断某个序列是符合队列的使用规则(先进先出),还是优先队列的使用顺序(默认数大的先出),还是栈的使用顺序。或者都不符合以及多个符合可能 。

         因为这些数据结构都是存在于stl的,所以你直接可以建一个跟着他一块模拟就好~~不过小心一下辣个,就是对于某个队列(栈)而言,他的首项存在是必须在队列(栈)size大于0(或者说是不为空)的情况下,~不能随意输出首项或者pop哦(注意)~~

#include<bits/stdc++.h>
using namespace std;
struct fuck {
	int type, num;
}m[100005];
int n;
int que() {
	queue<int>q;
	for (int i = 0; i < n; i++) {
		if (m[i].type == 1) {
			q.push(m[i].num);
		}
		else {
			if (q.empty())
				return 0;
			if (q.front() != m[i].num)
				return 0;
			q.pop();
		}
	}
	return 1;
}
int pri() {
	priority_queue<int>q;
	for (int i = 0; i < n; i++) {
		if (m[i].type == 1) {
			q.push(m[i].num);
		}
		else {
			if (q.empty())
				return 0;
			if (q.top() != m[i].num)
				return 0;
			q.pop();
		}
	}
	return 1;
}
int sta() {
	stack<int>q;
	for (int i = 0; i < n; i++) {
		if (m[i].type == 1) {
			q.push(m[i].num);
		}
		else {
			if (q.empty())
				return 0;
			if (q.top() != m[i].num)
				return 0;
			q.pop();
		}
	}
	return 1;
}
int main() {
	ios::sync_with_stdio(0);
	while (cin >> n) {
		for (int i = 0; i < n; i++) {
			cin >> m[i].type >> m[i].num;
		}
		int a = que(), b = pri(), c = sta();
		if (a + b + c >1) {
			cout << "not sure" << endl;
		}
		else if (a + b + c == 0) {
			cout << "impossible" << endl;
		}
		else {
			if (a == 1) {
				cout << "queue" << endl;
			}
			else if (b == 1) {
				cout << "priority queue" << endl;
			}
			else {
				cout << "stack" << endl;
			}
		}
	}
	return 0;
}

J - 4 Values whose Sum is 0

        四个序列求能使Ai+Bj+Ck+Dl=0的情况到底有几种。

       与题目D的情况相似。在这种情况下可以分成两组。一个是ans1,一个是ans2,分别代表着a+b的左右可能以及c+d的左右可能~~,然后遍历ans1数组,对于每个值查询在ans2中有几个-ans1[i]的值从而使a+b+c+d=0;这里的查询数量我用的lower_bound以及upper_bound,距离含义自己可以去查一查(别忘了用之前数组先排序)。

#include<bits/stdc++.h>
using namespace std;
int a[4005], b[4005], c[4005], d[4005];
int ans1[16000002], ans2[16000002];
int main() {
	int te, pot = 0;
	scanf("%d", &te);
	while (te--) {
		int n, ans = 0, cnt = 0;
		if (pot != 0)printf("\n");
		pot = 1;
		scanf("%d", &n);
		for (int i = 0; i < n; i++) {
			scanf("%d%d%d%d", &a[i], &b[i], &c[i], &d[i]);
		}
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				int t = a[i] + b[j];
				ans1[cnt++] = t;
			}
		}
		cnt = 0;
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				int t = c[i] + d[j];
				ans2[cnt++] = t;
			}
		}
		sort(ans1, ans1 + n*n);
		sort(ans2, ans2 + n*n);
		int last = 0;
		for (int i = 0; i < n*n; i++) {
			if (i != 0 && ans1[i] == ans1[i - 1]) {
				ans += last;
				continue;
			}
			int need = -ans1[i];
			int pos1 = lower_bound(ans2, ans2 + n*n, need) - ans2;
			int pos2 = upper_bound(ans2, ans2 + n*n, need) - ans2;
			ans += (pos2 - pos1);
			last = pos2 - pos1;
		}
		printf("%d\n", ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/chenshibo17/article/details/86677820