1063. Set Similarity (25)

1.该题目主要是先输入一些集合,然后查询某两个集合的交集数量除以并集数量。

2.刚开始使用map去存储每个集合,后面再建立一个新的map合并两个集合的map,从而查找交集数量,结果超时。

3.后面改为利用map作集合的重复判断,在输入集合时,通过map的判断,建立一个每个元素都是唯一的vector。

4.合并时,直接申请两个集合数量总和大小的新vector,把两个集合的vector复制进去,然后进行排序,通过检测元素是否出现两次,来实现检测交集。

5.新vector的size减去交集大小,就是并集。

6.通过这种数据结构和方法,成功AC题目。

1063

时间限制
300 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

Given two sets of integers, the similarity of the sets is defined to be Nc/Nt*100%, where Nc is the number of distinct common numbers shared by the two sets, and Nt is the total number of distinct numbers in the two sets. Your job is to calculate the similarity of any given pair of sets.

Input Specification:

Each input file contains one test case. Each case first gives a positive integer N (<=50) which is the total number of sets. Then N lines follow, each gives a set with a positive M (<=104) and followed by M integers in the range [0, 109]. After the input of sets, a positive integer K (<=2000) is given, followed by K lines of queries. Each query gives a pair of set numbers (the sets are numbered from 1 to N). All the numbers in a line are separated by a space.

Output Specification:

For each query, print in one line the similarity of the sets, in the percentage form accurate up to 1 decimal place.

Sample Input:

3
3 99 87 101
4 87 101 5 87
7 99 101 18 5 135 18 99
2
1 2
1 3

Sample Output:

50.0%
33.3%

 
AC代码:

//#include<string>
//#include<stack>
//#include<unordered_set>
//#include <sstream>
//#include "func.h"
//#include <list>
#include <iomanip>
#include<unordered_map>
#include<set>
#include<queue>
#include<map>
#include<vector>
#include <algorithm>
#include<stdio.h>
#include<iostream>
#include<string>
#include<memory.h>
#include<limits.h>
#include<stack>
using namespace std;

int main(void)
{
	int total;
	scanf("%d", &total);
	vector<map<int, int>> m(total);
	vector<vector<int>> ele(total);
	for (int i = 0; i < total; i++)
	{
		int n;
		scanf("%d", &n);
		for (int j = 0; j < n; j++)
		{
			int tmp;
			scanf("%d", &tmp);
			if (m[i][tmp] == 0)
			{
				m[i][tmp] = 1;
				ele[i].push_back(tmp);
			}
		}
	}
	int querySum;
	scanf("%d", &querySum);
	for (int i = 0; i < querySum; i++)
	{
		int a;
		int b;
		scanf("%d %d", &a, &b);
		a--;
		b--;
		vector<int> cal(ele[a].size() + ele[b].size());
		for (int i = 0; i < ele[a].size(); i++)
		{
			cal[i] = ele[a][i];
		}
		for (int i = ele[a].size(); i < ele[a].size() + ele[b].size(); i++)
		{
			cal[i] = ele[b][i - ele[a].size()];
		}
		double same = 0;
		sort(cal.begin(), cal.end());
		for (int i = 0; i < cal.size()-1; i++)
		{
			if (cal[i] == cal[i + 1])
				same++;
		}
		double ans = same / (cal.size() - same) * 100;
		printf("%.1lf%\n", ans);
	}
	return 0;
}

1062. Talent and Virtue (25)

1.给出一些ID及对应的天赋和美德分数,主要涉及到一个根据规则排序的问题。

2.分类规则:

1)圣人,sages,virtue和talent都要>=high

2)君子,nobleman,virtue>=high,talent<high,talent>=low

3)愚人,fool man,low<=talent<=virtue<high

4)愚人之后仍显示的,virtue>=low,talent>=low

3.跟结构体增加了一个level的变量,记录其所在的等级,排序比较函数如下:

bool cmp(const ManNode&a, const ManNode&b)
{
	if (a.level > b.level)
		return true;
	else if (a.level == b.level && a.total > b.total)
		return true;
	else if (a.level == b.level && a.total == b.total&& a.virtue > b.virtue)
		return true;
	else if (a.level == b.level && a.total == b.total&& a.virtue == b.virtue&& a.id < b.id)
		return true;
	else
		return false;
}

1062

时间限制
200 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Li

About 900 years ago, a Chinese philosopher Sima Guang wrote a history book in which he talked about people’s talent and virtue. According to his theory, a man being outstanding in both talent and virtue must be a “sage(圣人)”; being less excellent but with one’s virtue outweighs talent can be called a “nobleman(君子)”; being good in neither is a “fool man(愚人)”; yet a fool man is better than a “small man(小人)” who prefers talent than virtue.

Now given the grades of talent and virtue of a group of people, you are supposed to rank them according to Sima Guang’s theory.

Input Specification:

Each input file contains one test case. Each case first gives 3 positive integers in a line: N (<=105), the total number of people to be ranked; L (>=60), the lower bound of the qualified grades — that is, only the ones whose grades of talent and virtue are both not below this line will be ranked; and H (<100), the higher line of qualification — that is, those with both grades not below this line are considered as the “sages”, and will be ranked in non-increasing order according to their total grades. Those with talent grades below H but virtue grades not are cosidered as the “noblemen”, and are also ranked in non-increasing order according to their total grades, but they are listed after the “sages”. Those with both grades below H, but with virtue not lower than talent are considered as the “fool men”. They are ranked in the same way but after the “noblemen”. The rest of people whose grades both pass the L line are ranked after the “fool men”.

Then N lines follow, each gives the information of a person in the format:

ID_Number Virtue_Grade Talent_Grade

where ID_Number is an 8-digit number, and both grades are integers in [0, 100]. All the numbers are separated by a space.Output Specification:

The first line of output must give M (<=N), the total number of people that are actually ranked. Then M lines follow, each gives the information of a person in the same format as the input, according to the ranking rules. If there is a tie of the total grade, they must be ranked with respect to their virtue grades in non-increasing order. If there is still a tie, then output in increasing order of their ID’s.

Sample Input:

14 60 80
10000001 64 90
10000002 90 60
10000011 85 80
10000003 85 80
10000004 80 85
10000005 82 77
10000006 83 76
10000007 90 78
10000008 75 79
10000009 59 90
10000010 88 45
10000012 80 100
10000013 90 99
10000014 66 60

Sample Output:

12
10000013 90 99
10000012 80 100
10000003 85 80
10000011 85 80
10000004 80 85
10000007 90 78
10000006 83 76
10000005 82 77
10000002 90 60
10000014 66 60
10000008 75 79
10000001 64 90

 
AC代码:

//#include<string>
//#include<stack>
//#include<unordered_set>
//#include <sstream>
//#include "func.h"
//#include <list>
#include <iomanip>
#include<unordered_map>
#include<set>
#include<queue>
#include<map>
#include<vector>
#include <algorithm>
#include<stdio.h>
#include<iostream>
#include<string>
#include<memory.h>
#include<limits.h>
#include<stack>
using namespace std;

struct ManNode{
	int id;//输出时要注意是8位
	int virtue, talent;
	int level, total;
	ManNode() :id(0), virtue(0), talent(0), level(0), total(0){};

};
bool cmp(const ManNode&a, const ManNode&b)
{
	if (a.level > b.level)
		return true;
	else if (a.level == b.level && a.total > b.total)
		return true;
	else if (a.level == b.level && a.total == b.total&& a.virtue > b.virtue)
		return true;
	else if (a.level == b.level && a.total == b.total&& a.virtue == b.virtue&& a.id < b.id)
		return true;
	else
		return false;
}
int main(void)
{
	int manSum, low, high;
	cin >> manSum >> low >> high;
	vector<ManNode> man(manSum);
	for (int i = 0; i < man.size(); i++)
	{
		scanf("%d %d %d", &man[i].id, &man[i].virtue, &man[i].talent);
		man[i].total = man[i].virtue + man[i].talent;
		if (man[i].virtue >= high&&man[i].talent >= high)
			man[i].level = 4;//圣人,sages
		else if (man[i].virtue >= high&&man[i].talent < high && man[i].talent >= low)
			man[i].level = 3;//君子,nobleman
		else if (man[i].virtue < high && man[i].virtue >= man[i].talent && man[i].talent>=low)
			man[i].level = 2;//愚人,fool man
		else if (man[i].virtue >= low&&man[i].talent >= low)
			man[i].level = 1;//排在愚人之后,其他的不显示

	}
	sort(man.begin(), man.end(), cmp);

	int outPut = 0;
	for (int i = 0; i < man.size(); i++)
	{//统计需要显示的人数
		if (man[i].level>=1)
			outPut++;
		else
			break;
	}
	cout << outPut << endl;
	for (int i = 0; i < outPut; i++)
	{
		printf("%08d %d %d\n", man[i].id, man[i].virtue, man[i].talent);
	}

	return 0;
}

1061. Dating (20)

1.根据给出的规则对string进行匹配解密。

2.第一对string中,DAY的char需要限制在A到G之间,一个星期只有7天;HOUR的char需要限制在A到N,0到9之间,这样才是合理的0~23小时

3.之前卡在了没有限制HOUR的char需要限制在A到N,0到9之间。

时间限制
50 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

Sherlock Holmes received a note with some strange strings: “Let’s date! 3485djDkxh4hhGE 2984akDfkkkkggEdsb s&hgsfdk d&Hyscvnm”. It took him only a minute to figure out that those strange strings are actually referring to the coded time “Thursday 14:04” — since the first common capital English letter (case sensitive) shared by the first two strings is the 4th capital letter ‘D’, representing the 4th day in a week; the second common character is the 5th capital letter ‘E’, representing the 14th hour (hence the hours from 0 to 23 in a day are represented by the numbers from 0 to 9 and the capital letters from A to N, respectively); and the English letter shared by the last two strings is ‘s’ at the 4th position, representing the 4th minute. Now given two pairs of strings, you are supposed to help Sherlock decode the dating time.

Input Specification:

Each input file contains one test case. Each case gives 4 non-empty strings of no more than 60 characters without white space in 4 lines.

Output Specification:

For each test case, print the decoded time in one line, in the format “DAY HH:MM”, where “DAY” is a 3-character abbreviation for the days in a week — that is, “MON” for Monday, “TUE” for Tuesday, “WED” for Wednesday, “THU” for Thursday, “FRI” for Friday, “SAT” for Saturday, and “SUN” for Sunday. It is guaranteed that the result is unique for each case.

Sample Input:

3485djDkxh4hhGE 
2984akDfkkkkggEdsb 
s&hgsfdk 
d&Hyscvnm

Sample Output:

THU 14:04

 
AC代码:

//#include<string>
//#include<stack>
//#include<unordered_set>
//#include <sstream>
//#include "func.h"
//#include <list>
#include <iomanip>
#include<unordered_map>
#include<set>
#include<queue>
#include<map>
#include<vector>
#include <algorithm>
#include<stdio.h>
#include<iostream>
#include<string>
#include<memory.h>
#include<limits.h>
#include<stack>
using namespace std;
 
 
 
int main(void)
{
    string num2Day[] = { "", "MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN" };
    string first1, first2, second1, second2;
    //getline(cin, first1);
    //getline(cin, first2);
    //getline(cin, second1);
    //getline(cin, second2);
    cin >> first1>> first2>> second1>> second2;
    char dayChar = -1;
    char hourChar = -1;
    for (int i = 0; i < min(first1.size(), first2.size()); i++)
    {
        if (first1[i] == first2[i] &&( (first1[i] >= 'A'&&first1[i] <= 'N') || (first1[i] >= '0'&&first1[i] <= '9')))
        {//需要限制在A到N,0到9之间,这样才是合适的0~23小时显示,否则会出现测试点不过
            if (dayChar == -1 && (first1[i] >= 'A'&&first1[i] <= 'N'))
                dayChar = first1[i];
            else if (dayChar != -1)
            {
                hourChar = first1[i];
                break;
            }
        }
    }
    int mm;
    for (int i = 0; i < min(second1.size(), second2.size()); i++)
    {
        if (second1[i] == second2[i] && ((second1[i] >= 'A'&&second1[i] <= 'Z') || (second1[i] >= 'a'&&second1[i] <= 'z')))
        {
            mm = i;
            break;
        }
    }
    string day = num2Day[dayChar - 'A' + 1];
    string hour = "";
    int hourInt;
    if (hourChar >= 'A'&&hourChar <= 'Z')
        hourInt = hourChar - 'A' + 10;
    else
        hourInt = hourChar - '0';
    char c = hourInt / 10 + '0';
    hour += c;
    c = hourInt % 10 + '0';
    hour += c;
    cout << day << " " << hour;
    printf(":%02d\n", mm);
 
 
    return 0;
}

1060. Are They Equal (25)

1.题目要求把两个数分别转换成一定精度的数,用科学计数法显示,然后判断两个数是否相等。

2.下面列出了一些测试点,通过这些测试点,也就可以AC了:

3 12300 12358.9
YES 0.123*10^5

1 12300 12358.9
YES 0.1*10^5

1 1.2300 1.23589
YES 0.1*10^1

5 1.2300 1.23589
NO 0.12300*10^1 0.12358*10^1

4 0.01234 0.012345
YES 0.1234*10^-1

5 0.01234 0.012345
NO 0.12340*10^-1 0.12345*10^-1

5 0.1234 0.12345
NO 0.12340*10^0 0.12345*10^0

0 0.11 0
YES 0.*10^0或者YES 0.0*10^0,都可以AC,测试点应该没有这个例子

1 0.1 0
NO 0.1*10^0 0.0*10^0

1 0.0 0.1
NO 0.0*10^0 0.1*10^0

1 0.0 0.000
YES 0.0*10^0

1 00.0 0.000
YES 0.0*10^0

4 00.0 0.000
YES 0.0000*10^0

5 00.0 0.000
YES 0.00000*10^0

1 05.0 5.000
YES 0.5*10^1

1 00.01 0.010
YES 0.1*10^-1

1060

 

时间限制
50 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

If a machine can save only 3 significant digits, the float numbers 12300 and 12358.9 are considered equal since they are both saved as 0.123*105 with simple chopping. Now given the number of significant digits on a machine and two float numbers, you are supposed to tell if they are treated equal in that machine.

Input Specification:

Each input file contains one test case which gives three numbers N, A and B, where N (<100) is the number of significant digits, and A and B are the two float numbers to be compared. Each float number is non-negative, no greater than 10100, and that its total digit number is less than 100.

Output Specification:

For each test case, print in a line “YES” if the two numbers are treated equal, and then the number in the standard form “0.d1…dN*10^k” (d1>0 unless the number is 0); or “NO” if they are not treated equal, and then the two numbers in their standard form. All the terms must be separated by a space, with no extra space at the end of a line.

Note: Simple chopping is assumed without rounding.

Sample Input 1:

3 12300 12358.9

Sample Output 1:

YES 0.123*10^5

Sample Input 2:

3 120 128

Sample Output 2:

NO 0.120*10^3 0.128*10^3

AC代码,一定要自己写一遍才知道坑所在:

//#include<string>
//#include<stack>
//#include<unordered_set>
//#include <sstream>
//#include "func.h"
//#include <list>
#include <iomanip>
#include<unordered_map>
#include<set>
#include<queue>
#include<map>
#include<vector>
#include <algorithm>
#include<stdio.h>
#include<iostream>
#include<string>
#include<memory.h>
#include<limits.h>
#include<stack>
using namespace std;
/*
3 12300 12358.9
YES 0.123*10^5

1 12300 12358.9
YES 0.1*10^5

1 1.2300 1.23589
YES 0.1*10^1

5 1.2300 1.23589
NO 0.12300*10^1 0.12358*10^1

4 0.01234 0.012345
YES 0.1234*10^-1

5 0.01234 0.012345
NO 0.12340*10^-1 0.12345*10^-1

5 0.1234 0.12345
NO 0.12340*10^0 0.12345*10^0

0 0.11 0
YES 0.*10^0或者YES 0.0*10^0,都可以AC,测试点应该没有这个例子

1 0.1 0
NO 0.1*10^0 0.0*10^0

1 0.0 0.1
NO 0.0*10^0 0.1*10^0

1 0.0 0.000
YES 0.0*10^0

1 00.0 0.000
YES 0.0*10^0

4 00.0 0.000
YES 0.0000*10^0

5 00.0 0.000
YES 0.00000*10^0

1 05.0 5.000
YES 0.5*10^1

1 00.01 0.010
YES 0.1*10^-1
*/
bool isNum(char c)
{
	return (c <= '9'&&c >= '0');
}
string fixN(int n, string s)
{//如果不足N位,则补0,如果超过n位,则截断
	if (n == 0) return "0";
	if (s.size() >= n)
		return s.substr(0, n);
	else
	{
		//return s;//不补0,也可以
		int size = s.size();//在这里卡住了,本来下面的条件是i<n-s.size()+1,这样的话随着s补零,s的长度发生变化
		for (int i = 0; i < n - size; i++)
			s += '0';
		return s;//补0,也可以
	}
}
string num2String(int a)
{
	if (a == 0) return "0";
	string ans = "";
	while (a != 0)
	{
		char c = a % 10 + '0';
		ans += c;
		a /= 10;
	}
	return ans;
}
string trans(int n, string str)
{

	if (str == "0")
	{
		string tmp = "";
		for (int i = 0; i < n - str.size() + 1; i++)
			tmp += '0';
		if (tmp == "") tmp = "0";
		return str + "." + tmp + "*10^0";
	}
	else if (str[0] == '0')
	{//小数:0.1   0.0001
		int p = 0;
		string tmp = "";
		for (int i = 0; i < str.size(); i++)
		{
			if (isNum(str[i]))
				tmp += str[i];
		}

		tmp = tmp.substr(1);//除去整数位的0
		for (int i = 0; i < tmp.size(); i++)
		{//0.00001  有四个连续的0
			if (tmp[i] == '0')
				p++;//计算前面有多少个连续的0
			else break;
		}
		tmp = tmp.substr(p);
		if (tmp == "") p = 0;//如0.0,此时的tmp为0,p为1,截掉后tmp为空,p还有1,p应为0
		tmp = fixN(n, tmp);
		if (p == 0)
			return "0." + tmp + "*10^" + num2String(p);
		else
			return "0." + tmp + "*10^-" + num2String(p);


	}
	else
	{//大于1的数
		int p = -1;//小数点位置
		string tmp = "";
		for (int i = 0; i < str.size(); i++)
		{
			if (isNum(str[i]))
				tmp += str[i];
			if (p == -1 && str[i] == '.')
				p = i;//求得小数点的位置
		}

		if (p == -1)//str多少位,就有多少个10,如1234
			p = str.size();

		tmp = fixN(n, tmp);
		string ans = "0." + tmp + "*10^" + num2String(p);
		return ans;
	}
}
string deleteZero(string a)
{
	int p = 0;
	for (int i = 0; i < a.size() - 1; i++)
	{
		if (a[i] == '0'&&a[i + 1] != '.')
			p++;
		else
			break;
	}
	return a.substr(p);
}
int main(void)
{
	int n;
	string a, b;
	cin >> n >> a >> b;
	//if (n == 0)
	//{//这部分输出YES 0.*10^0或者YES 0.0*10^0,都可以AC,测试点应该没有这个例子
	//	cout << "YES 0.0*10^0" << endl;
	//	return 0;
	//}
	string a2 = trans(n, deleteZero(a));
	b = deleteZero(b);
	string b2 = trans(n, b);
	if (a2 == b2)
		cout << "YES " << a2 << endl;
	else
		cout << "NO " << a2 << " " << b2 << endl;

	return 0;
}

1059. Prime Factors (25)

1.题目要求求一个数的质因数分解。

2.一个大于等于2的数,质因数分解分两种情况:

1)如果这个数是质数,那么质因数分解就是它本身;

2)如果不是质数,那么除去最大的质因数后,剩下的质因数均小于sqrt(n),所以遍历到sqrt(n)即可。

3.注意输入为1的情况,输出应该为1=1。

1059

时间限制
50 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
HE, Qinming

Given any positive integer N, you are supposed to find all of its prime factors, and write them in the format N = p1^k1* p2^k2 *…*pm^km.

Input Specification:

Each input file contains one test case which gives a positive integer N in the range of long int.

Output Specification:

Factor N in the format N = p1^k1 * p2^k2 *…*pm^km, where pi‘s are prime factors of N in increasing order, and the exponent ki is the number of pi — hence when there is only one pi, ki is 1 and must NOT be printed out.

Sample Input:

97532468

Sample Output:

97532468=2^2*11*17*101*1291

 
AC代码:

//#include<string>
//#include<stack>
//#include<unordered_set>
//#include <sstream>
//#include "func.h"
//#include <list>
#include <iomanip>
#include<unordered_map>
#include<set>
#include<queue>
#include<map>
#include<vector>
#include <algorithm>
#include<stdio.h>
#include<iostream>
#include<string>
#include<memory.h>
#include<limits.h>
#include<stack>
using namespace std;

int main(void)
{
	int n;
	cin >> n;
	int outPur = n;

	vector<pair<int, int>> factor(0);

	int tmp = sqrt(n) + 1;
	for (int i = 2; i <= tmp; i++)
	{//遍历到sqrt(n)+1即可
		if (n%i == 0)
		{
			factor.push_back({ i, 1 });
			n /= i;
			while (n%i == 0)
			{
				factor.back().second++;
				n /= i;
			}
		}
	}
	if (n != 1)//如果最后不为1,那么这个是最大质因数
		factor.push_back({ n, 1 });
	if (outPur == 1)
	{//注意1的情况
		printf("1=1\n");
		return 0;
	}
	printf("%d=", outPur);
	for (int i = 0; i < factor.size(); i++)
	{
		printf("%d", factor[i].first);
		if (factor[i].second != 1)
			printf("^%d", factor[i].second);
		if (i != factor.size() - 1)
			printf("*");
	}
	cout << endl;

	return 0;
}

1058. A+B in Hogwarts (20)

1.给出两个数,根据题目要求进行加法运算。

2.该题不难,主要是字符串的处理和进制处理。

时间限制
50 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

If you are a fan of Harry Potter, you would know the world of magic has its own currency system — as Hagrid explained it to Harry, “Seventeen silver Sickles to a Galleon and twenty-nine Knuts to a Sickle, it’s easy enough.” Your job is to write a program to compute A+B where A and B are given in the standard form of “Galleon.Sickle.Knut” (Galleon is an integer in [0, 107], Sickle is an integer in [0, 17), and Knut is an integer in [0, 29)).

Input Specification:

Each input file contains one test case which occupies a line with A and B in the standard form, separated by one space.

Output Specification:

For each test case you should output the sum of A and B in one line, with the same format as the input.

Sample Input:

3.2.1 10.16.27

Sample Output:

14.1.28

AC代码:

//#include<string>
//#include<stack>
//#include<unordered_set>
//#include <sstream>
//#include "func.h"
//#include <list>
#include <iomanip>
#include<unordered_map>
#include<set>
#include<queue>
#include<map>
#include<vector>
#include <algorithm>
#include<stdio.h>
#include<iostream>
#include<string>
#include<memory.h>
#include<limits.h>
#include<stack>
using namespace std;

bool isNum(char c)
{
	if (c <= '9'&&c >= '0') return true;
	else return false;
}
void string2Num(string a,int&a1, int&a2, int&a3)
{
	int idx = 0;
	for (int i = 0; i < a.size(); i++)
	{
		if (idx == 0 && isNum(a[i]))
			a1 = a1 * 10 + a[i] - '0';
		else if (idx == 1 && isNum(a[i]))
			a2 = a2 * 10 + a[i] - '0';
		else if (idx == 2 && isNum(a[i]))
			a3 = a3 * 10 + a[i] - '0';
		else if (a[i] == '.')
		{
			idx++;
		}
	}
}
int main(void)
{
	
	string a, b;
	cin >> a >> b;
	int a1 = 0, a2 = 0, a3 = 0;
	int b1 = 0, b2 = 0, b3 = 0;

	string2Num(a, a1, a2, a3);
	string2Num(b, b1, b2, b3);

	int carry = 0;
	a3 = a3 + b3;
	carry = a3 / 29;
	a3 %= 29;
	a2 = a2 + b2 + carry;
	carry = a2 / 17;
	a2 %= 17;
	a1 = a1 + b1 + carry;

	printf("%d.%d.%d\n", a1, a2, a3);

	return 0;
}

1057. Stack (30)

1.该题重点!主要是模拟栈操作,能够频繁读取栈中元素的中位数。

2.本题的中间三个测试点非常容易超时。

3.需要采用树状数组+二分法

树状数组:能够在o(logn)的时间内进行对a[i]操作和统计a[0]+a[1]+a[2]+…a[i]的操作。

我们把a[i]记录为i的出现次数,那么统计sum=a[0]+a[1]+a[2]+…a[i],就可以知道小于等于i的元素出现的次数。而PeekMedian操作中,是求n/2或者(n+1)/2的元素,即当sum等于n/2或者(n+1)/2时,i就是我们需要输出的元素

4.利用树状数组,能够快速统计sum,利用二分法,能够快速定位i。

5.后续优化:可以考虑采用一个数组实现stack的功能,int stack[N];   int stackTop=0;//既是栈顶元素在stack数组的位置,也是栈内元素的总个数,push操作:stack[++stackTop]=x,  pop操作:stack[stackTop–].

20151127190935810

时间限制
100 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

Stack is one of the most fundamental data structures, which is based on the principle of Last In First Out (LIFO). The basic operations include Push (inserting an element onto the top position) and Pop (deleting the top element). Now you are supposed to implement a stack with an extra operation: PeekMedian — return the median value of all the elements in the stack. With N elements, the median value is defined to be the (N/2)-th smallest element if N is even, or ((N+1)/2)-th if N is odd.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer N (<= 105). Then N lines follow, each contains a command in one of the following 3 formats:

Push key
Pop
PeekMedianwhere key is a positive integer no more than 105.

Output Specification:

For each Push command, insert key into the stack and output nothing. For each Pop or PeekMedian command, print in a line the corresponding returned value. If the command is invalid, print “Invalid” instead.

Sample Input:

17
Pop
PeekMedian
Push 3
PeekMedian
Push 2
PeekMedian
Push 1
PeekMedian
Pop
Pop
Push 5
Push 4
PeekMedian
Pop
Pop
Pop
Pop

Sample Output:

Invalid
Invalid
3
2
2
1
2
4
4
5
3
Invalid

 
AC代码:

//#include<string>
//#include<stack>
//#include<unordered_set>
//#include <sstream>
//#include "func.h"
//#include <list>
#include <iomanip>
#include<unordered_map>
#include<set>
#include<queue>
#include<map>
#include<vector>
#include <algorithm>
#include<stdio.h>
#include<iostream>
#include<string>
#include<memory.h>
#include<limits.h>
#include<stack>
using namespace std;
#define MAX_N 100001

int Tree[MAX_N];
inline int lowbit(int x)
{
	return(x&-x);
}

void add(int x, int value)
{
	for (int i = x; i < MAX_N; i += lowbit(i))
		Tree[i] += value;
}
int get(int x)
{//获取0到x的数组总和
	int sum = 0;
	for (int i = x; i; i -= lowbit(i))
		sum += Tree[i];
	return sum;
}

int main(void)
{
	int n;
	cin >> n;
	char action[11];
	stack<int> sta;
	int maxNum = INT_MIN;
	int minNum = INT_MAX;
	memset(Tree, 0, sizeof(Tree));
	for (int i = 0; i < n; i++)
	{
		scanf("%s", action);
		if (action[2] == 'p')
		{//pop
			if (sta.empty())
			{
				cout << "Invalid" << endl;
				continue;
			}
			int top = sta.top();
			sta.pop();
			add(top, -1);//弹出,出现次数减1
			printf("%d\n", top);
		}
		else if (action[2] == 'e')
		{//PeekMedian
			if (sta.empty())
			{
				cout << "Invalid" << endl;
				continue;
			}
			int n = sta.size();//栈里的元素个数
			int target = 0;
			if (n % 2 == 0)
				target = n / 2;
			else
				target = (n + 1) / 2;

			//设中位数为i,用二分法查找
			int l = 0;
			int r = MAX_N - 1;
			while (l <r - 1)
			{
				int mid = (l + r) / 2;
				if (get(mid) < target)
					l = mid;
				else//如果get(mid)<=target,则r=mid,逐渐逼近
					r = mid;
			}
			printf("%d\n", l + 1);
		}
		else
		{//push
			int tmp;
			scanf("%d", &tmp);
			sta.push(tmp);
			maxNum = max(maxNum, tmp);
			minNum = min(minNum, tmp);
			add(tmp, 1);//弹出,出现次数加1
		}
	}
	return 0;
}

1056. Mice and Rice (25)

1.题目的要求是,每次选取NG个用户组成一组进行比赛,第一名进入下一轮,其他落败的用户排名相同。

2.刚开始卡在了这里,误以为在最后议论的比赛中,用户要排1,2,3,4。。结果不是,最后一轮,胜出的排第一名,落败的均为第二名。

3.排名的统计,假如这次有N个group,那么这次落败的用户排名为N+1。

4.第三个数组是用户次序,如6 0 8 7 10 5 9 1 4 2 3

则分组为:

6 0 8

7 10 5

9 1 4

2 3

共四个组

1056

时间限制
30 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

Mice and Rice is the name of a programming contest in which each programmer must write a piece of code to control the movements of a mouse in a given map. The goal of each mouse is to eat as much rice as possible in order to become a FatMouse.

First the playing order is randomly decided for NP programmers. Then every NG programmers are grouped in a match. The fattest mouse in a group wins and enters the next turn. All the losers in this turn are ranked the same. Every NGwinners are then grouped in the next match until a final winner is determined.

For the sake of simplicity, assume that the weight of each mouse is fixed once the programmer submits his/her code. Given the weights of all the mice and the initial playing order, you are supposed to output the ranks for the programmers.

Input Specification:

Each input file contains one test case. For each case, the first line contains 2 positive integers: NP and NG (<= 1000), the number of programmers and the maximum number of mice in a group, respectively. If there are less than NG mice at the end of the player’s list, then all the mice left will be put into the last group. The second line contains NP distinct non-negative numbers Wi (i=0,…NP-1) where each Wiis the weight of the i-th mouse respectively. The third line gives the initial playing order which is a permutation of 0,…NP-1 (assume that the programmers are numbered from 0 to NP-1). All the numbers in a line are separated by a space.

Output Specification:

For each test case, print the final ranks in a line. The i-th number is the rank of the i-th programmer, and all the numbers must be separated by a space, with no extra space at the end of the line.

Sample Input:

11 3
25 18 0 46 37 3 19 22 57 56 10
6 0 8 7 10 5 9 1 4 2 3

Sample Output:

5 5 5 2 5 5 5 3 1 3 5

 
AC代码:

//#include<string>
//#include<stack>
//#include<unordered_set>
//#include <sstream>
//#include "func.h"
//#include <list>
#include <iomanip>
#include<unordered_map>
#include<set>
#include<queue>
#include<map>
#include<vector>
#include <algorithm>
#include<stdio.h>
#include<iostream>
#include<string>
#include<memory.h>
#include<limits.h>
#include<stack>
using namespace std;
vector<int> weight;
bool cmp(const int&a, const int&b)
{
	return weight[a] > weight[b];
}
/*
11 3
25 18 0 46 37 3 19 22 57 56 10
6 0 8 7 10 5 9 1 4 2 3

11 3
25 18 0 46 37 3 19 22 57 56 10
0 1 2 3 4 5 6 7 8 9 10

11 11
25 18 0 46 37 3 19 22 57 56 10
0 1 2 3 4 5 6 7 8 9 10

11 10
25 18 0 46 37 3 19 22 57 56 10
0 1 2 3 4 5 6 7 8 9 10


11 10
0 1 2 3 4 5 6 7 8 9 10
0 1 2 3 4 5 6 7 8 9 10
10 5
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
10 4
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
10 3
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
10 2
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
10 1
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
*/
int main(void)
{

	int NP, NG;
	cin >> NP >> NG;
	weight = vector<int>(NP, 0);
	vector<int> order(NP, 0);
	vector<int> rank(NP, 0);
	for (int i = 0; i < NP; i++)
	{
		scanf("%d", &weight[i]);//输入老鼠重量
	}
	for (int i = 0; i < NP; i++)
	{
		scanf("%d", &order[i]);//输入选手的次数,order[i]号选手在i的位置
	}

	int thisCount = NP ;
	while (1)
	{
		int group;
		if (thisCount%NG == 0)
			group = thisCount / NG;
		else
			group = thisCount / NG + 1;
		//如果只有0组,或者刚好1组,则全部排名即可
		if (group <= 1)
		{
			sort(order.begin(), order.begin() + thisCount, cmp);
			rank[order[0]] =  1;//最后一轮,胜利者为第一名
			for (int i = 1; i < thisCount; i++)
			{//其他落败的名次相同,均为第2名
				rank[order[i]] = 2;
			}
			break;
		}
		else
		{
			int nextCount=0;
			for (int i = 0; i < group; i++)
			{
				int maxNum = order[i*NG];
				int maxWeight = weight[maxNum];
				for (int j = i*NG + 1; j < min((i + 1)*NG, thisCount); j++)
				{
					if (maxWeight < weight[order[j]])
					{//max落败
						rank[maxNum] = group + 1;
						maxWeight = weight[order[j]];
						maxNum = order[j];
					}
					else
					{//j落败
						rank[order[j]] = group + 1;
					}
				}
				//为了节省空间,把排名放在order的0~group-1的位置,不会干扰
				order[nextCount++]=maxNum;
			}
			thisCount = group;
		}
	}

	for (int i = 0; i < rank.size(); i++)
	{
		printf("%d", rank[i]);
		if (i != rank.size()-1)
			printf(" ");
	}
	cout << endl;
	return 0;
}

1055. The World’s Richest (25)

1.该题重点!题目给出一定的用户,包括用户年龄和净资产,要求后面按照年龄查询用户,按照一定的规则排序。

2.先把用户按照年龄大小排序,因为后面给出的是年龄范围,所以需要快速找出符合年龄要求的用户

3.建立一个年龄数组,该数组记录了以年龄x为左界时,用户数组的idx,以年龄x为右界时,用户数组的idx,通过年龄数组,就可以快速定位到用户数组的对应位置

4.刚开始,在查询输入时,直接定位到用户数组,把对应的用户数组段复制出来,进行排序,但是会超时(卡了还挺久的),然后仔细思考,发现用户数组的数量可能很大,<=100000,查询数量最大为2000,假如每次都复制100000,然后再进行排序,会严重浪费时间。

5.再观察题目,发现最终需要显示的数量最多只有100个,于是考虑建立一个小根堆,把它的大小维持在需要显示的数量showSum,最后复制输出即可。

为什么建立小根堆?我们的目的是要找出财富值最大的showSum个用户,建立小根堆,堆顶为showSum个用户中财富最小的,假如遍历用户j,发现用户j的财富值比小根堆的堆顶要大,那么把用户压入小根堆,再从小根堆中弹出堆顶即可。

1055

 

时间限制
400 ms
内存限制
128000 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

Forbes magazine publishes every year its list of billionaires based on the annual ranking of the world’s wealthiest people. Now you are supposed to simulate this job, but concentrate only on the people in a certain range of ages. That is, given the net worths of N people, you must find the M richest people in a given range of their ages.

Input Specification:

Each input file contains one test case. For each case, the first line contains 2 positive integers: N (<=105) – the total number of people, and K (<=103) – the number of queries. Then N lines follow, each contains the name (string of no more than 8 characters without space), age (integer in (0, 200]), and the net worth (integer in [-106, 106]) of a person. Finally there are K lines of queries, each contains three positive integers: M (<= 100) – the maximum number of outputs, and [Amin, Amax] which are the range of ages. All the numbers in a line are separated by a space.

Output Specification:

For each query, first print in a line “Case #X:” where X is the query number starting from 1. Then output the M richest people with their ages in the range [Amin, Amax]. Each person’s information occupies a line, in the format

Name Age Net_Worth

The outputs must be in non-increasing order of the net worths. In case there are equal worths, it must be in non-decreasing order of the ages. If both worths and ages are the same, then the output must be in non-decreasing alphabetical order of the names. It is guaranteed that there is no two persons share all the same of the three pieces of information. In case no one is found, output “None”.Sample Input:

12 4
Zoe_Bill 35 2333
Bob_Volk 24 5888
Anny_Cin 95 999999
Williams 30 -22
Cindy 76 76000
Alice 18 88888
Joe_Mike 32 3222
Michael 5 300000
Rosemary 40 5888
Dobby 24 5888
Billy 24 5888
Nobody 5 0
4 15 45
4 30 35
4 5 95
1 45 50

Sample Output:

Case #1:
Alice 18 88888
Billy 24 5888
Bob_Volk 24 5888
Dobby 24 5888
Case #2:
Joe_Mike 32 3222
Zoe_Bill 35 2333
Williams 30 -22
Case #3:
Anny_Cin 95 999999
Michael 5 300000
Alice 18 88888
Cindy 76 76000
Case #4:
None

AC代码:


//#include<string>
//#include<stack>
//#include<unordered_set>
//#include <sstream>
//#include "func.h"
//#include <list>
#include <iomanip>
#include<unordered_map>
#include<set>
#include<queue>
#include<map>
#include<vector>
#include <algorithm>
#include<stdio.h>
#include<iostream>
#include<string>
#include<memory.h>
#include<limits.h>
#include<stack>
using namespace std;
struct PeopleNode{
	int age, netWorth;
	char name[9];
	PeopleNode() :age(-1), netWorth(-1){};
};

bool cmp(const PeopleNode&a, const PeopleNode&b)
{//根据年龄排序
	if (a.age < b.age)
		return true;
	else
		return false;
}
struct cmpHeap{//根据题目的显示规则排序
	bool operator()(const PeopleNode&a, const PeopleNode&b)
	{
		if (a.netWorth > b.netWorth)
			return true;
		else if (a.netWorth == b.netWorth && a.age < b.age)
			return true;
		else if (a.netWorth == b.netWorth && a.age == b.age)
		{
			int asize = 0, bsize = 0;
			for (int i = 0; i < 9; i++)
			{
				if (a.name[i] != 0)
					asize++;
				else
					break;
			}
			for (int i = 0; i < 9; i++)
			{
				if (b.name[i] != 0)
					bsize++;
				else
					break;
			}
			for (int i = 0; i < min(asize, bsize); i++)
			{
				if (a.name[i] < b.name[i])
					return true;
				else if (a.name[i] > b.name[i])
					return false;
			}
			if (asize < bsize) return true;
			else return false;
		}
		else
			return false;
	}
};



int main(void)
{
	int peopleSum, querySum;
	scanf("%d %d", &peopleSum, &querySum);
	vector<PeopleNode> people(peopleSum);
	vector<vector<PeopleNode>> agePeople(201);
	for (int i = 0; i < peopleSum; i++)
	{
		scanf("%s %d %d", people[i].name, &people[i].age, &people[i].netWorth);
	}

	sort(people.begin(), people.end(), cmp);
	vector<pair<int, int>> ageRange(201, { -1, -1 });
	int idx = 0;

	//计算年龄范围数组
	for (int i = 0; i < ageRange.size(); i++)
	{
		if (idx < people.size())//确保idx在size内
		{
			if (idx == 0 && people[idx].age > i)
			{//idx不进行++,而i++,直到i和age相等
				ageRange[i].first = 0;
				ageRange[i].second = -1;//以-1作为右边界,意思是不存在年龄小于等于i的人
			}
			else if (idx != 0 && people[idx].age > i)
			{//idx不进行++,而i++,直到i和age相等
				ageRange[i].first = idx;//i岁的搜索的起始idx,以idx作为左边界
				ageRange[i].second = idx - 1;//i岁的搜索的终止idx,以idx-1作为右边界
			}
			else if (people[idx].age == i)
			{//如果i等于年龄
				ageRange[i].first = idx;
				while (idx < people.size() && people[idx].age == i)
				{//一直到age和i不相等
					idx++;
				}
				ageRange[i].second = idx - 1;//第idx个人的年龄不等于i,第idx-1个人的年龄等于i
			}
		}
		else if (i>0)
		{//如果i的值大于0,且idx超出范围(即已经遍历完用户)
			ageRange[i].first = people.size();//把i的左界设置为无效值
			ageRange[i].second = ageRange[i - 1].second;//把i的右界设置为用户idx的最大值
		}
	}

	for (int i = 0; i < querySum; i++)
	{
		int showSum, minA, maxA;
		scanf("%d %d %d", &showSum, &minA, &maxA);
		int sum = ageRange[maxA].second - ageRange[minA].first + 1;//求出以minA为左界,maxA为右界的people数量
		printf("Case #%d:\n", i + 1);
		if (sum > 0)
		{//存在用户,sum的数量可能很大,用户取值<=100000,但是需要显示的数量<=100,所以用一个小根堆来维护需要显示的人
			vector<PeopleNode>::iterator ite = people.begin();
			priority_queue<PeopleNode, vector<PeopleNode>, cmpHeap> q;
			for (int j = 0; j < sum; j++)
			{
				if (q.size() == showSum && q.top().netWorth <= (ite + j + ageRange[minA].first)->netWorth)
				{//如果小根堆的数量已经达到显示数量,但是小根堆的顶部财富小于等于当前遍历的财富值,则压入
					q.push(*((ite + j + ageRange[minA].first)));
					q.pop();//相应地,弹出一个
				}
				else if (q.size()<showSum)//如果小根堆还没满,直接压入即可
					q.push(*((ite + j + ageRange[minA].first)));

			}
			vector<PeopleNode> show(min(showSum, (int)q.size()));
			for (int j = show.size() - 1; j >= 0; j--)
			{//因为需要升序排列,用的是小根堆,所以把小根堆的堆顶放在数组尾部
				show[j] = q.top();
				q.pop();
			}
			for (int j = 0; j < show.size(); j++)
			{
				printf("%s %d %d\n", show[j].name, show[j].age, show[j].netWorth);
			}
		}
		else
		{//数量小于等于0,直接输出None
			printf("None\n");
			sum = 0;
		}

	}

	return 0;
}

1054. The Dominant Color (20)

1.该题求出现次数超过一半的元素,故采用moore voting算法,moore投票法。

2.遇到不同的元素,如果出现次数为0,更跟换成当前元素,如果次数不为0则-1。

3.遇到相同元素,出现次数相加。

4.最终记录的元素就是所求元素。

1054

时间限制
100 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

Behind the scenes in the computer’s memory, color is always talked about as a series of 24 bits of information for each pixel. In an image, the color with the largest proportional area is called the dominant color. A strictly dominant color takes more than half of the total area. Now given an image of resolution M by N (for example, 800×600), you are supposed to point out the strictly dominant color.

Input Specification:

Each input file contains one test case. For each case, the first line contains 2 positive numbers: M (<=800) and N (<=600) which are the resolutions of the image. Then N lines follow, each contains M digital colors in the range [0, 224). It is guaranteed that the strictly dominant color exists for each input image. All the numbers in a line are separated by a space.

Output Specification:

For each test case, simply print the dominant color in a line.

Sample Input:

5 3
0 0 255 16777215 24
24 24 0 0 24
24 0 24 24 24

Sample Output:

24
//#include<string>
//#include<stack>
//#include<unordered_set>
//#include <sstream>
//#include "func.h"
//#include <list>
#include <iomanip>
#include<unordered_map>
#include<set>
#include<queue>
#include<map>
#include<vector>
#include <algorithm>
#include<stdio.h>
#include<iostream>
#include<string>
#include<memory.h>
#include<limits.h>
#include<stack>
using namespace std;
int main(void)
{
	int m, n;
	cin >> m >> n;
	int count = 0, color = -1;
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < m; j++)
		{
			int tmpColor;
			scanf("%d", &tmpColor);
			if (color != tmpColor)
			{//元素不同
				if (count == 0)//更新元素
					color = tmpColor;
				else
					count--;
			}
			else//元素相同,出现次数累加
				count++;
		}
	}
	cout << color << endl;
	return 0;
}