乐师-理工ACM暑假集训-STL容器

文章目录

  • HDU4841 圆桌问题【模拟】
    • 题目描述
    • 测试样例
    • 解题思路
    • AC代码1【queue+模拟】
    • AC代码2【int数组+模拟】
  • AC代码3【char数组+模拟】
  • HDU1062 Text Reverse
    • 题目描述
    • 测试样例
    • 题目大意
    • 解题思路
    • AC代码1【char数组】
    • AC代码2【STL string】
  • HDU1702 ACboy needs your help again!【队列+栈】
    • 题目描述
    • 测试样例
    • 题目大意
    • 解题思路
    • AC代码
  • HDU1873 看病要排队【优先队列+自定义比较规则】
    • 题目描述
    • 测试样例
    • 解题思路
    • AC代码1
    • AC代码1简化版【优先队列数组】
  • HDU2648 Shopping【map】
    • 题目描述
    • 测试样例
    • 题目大意
    • 解题思路
    • AC代码

HDU4841 圆桌问题【模拟】

传送门:HDU4841 圆桌问题

题目描述

乐师-理工ACM暑假集训-STL容器_第1张图片

测试样例

Sample Input
2 3
2 4

Sample Output
GBBG

BGGB

解题思路

  我们事先肯定是无法得知哪些位置安排好人哪些位置安排坏人,所以只能模拟处死的过程,标记被处死人的编号。等模拟结束就知道哪些位置上应该安排好人,哪些位置应该安排坏人了。

AC代码1【queue+模拟】

#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int MAXN=7e4;
queue<int> q;
int vis[MAXN];
int main()
{
	int n,m;
	while(cin>>n>>m) // 多组数据,cin不用判断文件末尾
	{
		for(int i=1;i<=2*n;i++) // 2*n个人全部入队列
			q.push(i);
		int cnt=1;
		while(!q.empty()&&q.size()>n) //队列不为空且剩下人数大于n
		{
			int temp=q.front();
			q.pop();
			if(cnt==m) // 数到m处死
			{
				cnt=1; //重新计数
				vis[temp]=1; //标记该位置
			}
			else // 不会被处死
			{
				cnt++; // 继续计数
				q.push(temp); //回到队尾
			}
		}
		cnt=0;
		for(int i=1;i<=2*n;i++)
		{
			if(vis[i]==1) // 会被处死的位置安排坏人
				cout<<"B";
			else
				cout<<"G";
			cnt++;
			if(cnt==50) // 题中要求50个字母为一行
			{
				cout<<"\n";
				cnt=0;
			}
		}
		if(cnt<50) // 最后一行不满 50个字母也要换行
			cout<<"\n";
		cout<<"\n"; // 相邻数据间留有一空行
		while(!q.empty()) //清空队列中剩余人
			q.pop();
		memset(vis,0,sizeof(vis)); // 清空标记,批量初始化 vis数组为 0
	}
	return 0;
}

AC代码2【int数组+模拟】

#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int MAXN=7e4;
int vis[MAXN];
int main()
{
	int n,m;
	while(~scanf("%d%d",&n,&m)) // 多组数据
	{
		int cnt=1,size=0,ind=1;
		while(size<n) // 处死人数不足 n
		{
			if(!vis[ind]) // 该位置还有人在(未被处死)
			{
				if(cnt==m) // 数到 m处死
				{
					cnt=1; // 重新计数
					vis[ind]=1; // 标记该位置人被处死
					size++; // 处死人数加一
				}
				else
					cnt++; //计数
			}
			if(ind==2*n) // 轮转到末尾,从头开始
				ind=1;
			else // 继续轮转
				ind++;
		}
		cnt=0;
		for(int i=1;i<=2*n;i++)
		{
			if(vis[i]==1) // 会被处死的位置安排坏人
				printf("B");
			else
				printf("G");
			cnt++;
			if(cnt==50) // 题中要求50个字母为一行
			{
				printf("\n");
				cnt=0;
			}
		}
		if(cnt<50) // 最后一行不满 50个字母也要换行
			printf("\n");
		printf("\n"); // 相邻数据间留有一空行
		memset(vis,0,sizeof(vis)); // 清空标记,批量初始化 vis数组为 0
	}
	return 0;
}

AC代码3【char数组+模拟】

#include
const int MAXN=7e4;
char s[MAXN];
int main()
{
	int n,m;
	while(~scanf("%d%d",&n,&m))
	{
		for(int i=1;i<MAXN;i++) // 初始全部是好人
			s[i]='G';
		int num=0,cnt=0;;
		for(int i=1;num<n;i=(i%(2*n))+1) //轮转
		{
			if(s[i]=='B') //该位置的人已经被处死
				continue;
			cnt++;
			if(cnt==m) //数到m
			{
				cnt=0; // 重新计数
				s[i]='B'; // 该位置的人会被处死,安排坏人
				num++; // 坏人数+1
			}
		}
		for(int i=1;i<=2*n;i++)
		{
			printf("%c",s[i]);
			if(i%50==0) // 每 50个换行
				printf("\n");
		}
		if(2*n%50!=0) // 最后一行不到 50个
			printf("\n");
		printf("\n"); // 相邻数据换行
	}
	return 0;
}

HDU1062 Text Reverse

传送门:HDU1062 Text Reverse

题目描述

乐师-理工ACM暑假集训-STL容器_第2张图片

测试样例

Sample Input
3
olleh !dlrow
m'I morf .udh
I ekil .mca

Sample Output
hello world!
I'm from hdu.
I like acm.

Hint
Remember to use getchar() to read ‘\n’ after the interger T, then you may use gets() to read a line and process it.

题目大意

  T个测试样例,每个样例给定一行包含若干单词的文本,每个单词用空格隔开,要求输出反转每个单词后的文本。

解题思路

  对于一行文本,边读边存,当碰到空格或者读到末尾,倒序输出存的单词,并清空存储空间。
  注意看提示内容。要用读取输入T后的换行。

AC代码1【char数组】

#include
#include
const int MAXN=1e3+5;
char s[MAXN],temp[MAXN];
int ind=0;
int main()
{
	int T;
	scanf("%d",&T);
	getchar(); //读取输入T后的换行,避免下面的gets读到一个空串
	while(T--)
	{
		gets(s); // 读取整行
		ind=0;
		int len=strlen(s);
		for(int i=0;i<len;i++)
		{
			if(s[i]!=' ') // 不是空格,复制字母
				temp[ind++]=s[i];
			else // 碰到空格,说明一个单词结束
			{
				for(int j=ind-1;j>=0;j--) //反转输出
					printf("%c",temp[j]);
				printf(" "); // 输出空格
				ind=0; // 清空ans数组
			}
		}
		// 最后一个单词,末尾没有空格
		for(int j=ind-1;j>=0;j--)
			printf("%c",temp[j]);
		printf("\n");	
	}
	return 0;
}

AC代码2【STL string】

#include
#include
#include
using namespace std;
string s,temp;
int main()
{
	int T;
	cin>>T;
	cin.get(); //读取输入T后的换行,注意最好不要将 cin和 getchar()混合使用
	while(T--)
	{
		temp="";
		getline(cin,s); // 读取整行
		int len=s.size();
		for(int i=0;i<len;i++)
		{
			if(s[i]!=' ') // 不是空格,复制字母
				temp+=s[i];
			else // 碰到空格,说明一个单词结束
			{
				reverse(temp.begin(),temp.end());
				cout<<temp<<" ";
				temp="";
			}
		}
		// 最后一个单词,末尾没有空格
		reverse(temp.begin(),temp.end());
		cout<<temp<<"\n";	
	}
	return 0;
}

HDU1702 ACboy needs your help again!【队列+栈】

传送门:HDU1702 ACboy needs your help again!

题目描述

乐师-理工ACM暑假集训-STL容器_第3张图片

测试样例

Sample Input
4
4 FIFO
IN 1
IN 2
OUT
OUT
4 FILO
IN 1
IN 2
OUT
OUT
5 FIFO
IN 1
IN 2
OUT
OUT
OUT
5 FILO
IN 1
IN 2
OUT
IN 3
OUT

Sample Output
1
2
2
1
1
2
None
2
3

题目大意

  T个测试样例,每个样例第一行是整数N(命令数),以及单词“ FIFO”或“ FILO”。(“ FIFO”代表“先进先出”和“ FILO” 表示“先进先出”)。在接下来的N行中,每行是“ IN M”或“ OUT”(M代表整数)。对于“IN M”命令将执行入队列(栈)操作,对于OUT将执行出队列(栈)并输出操作。

解题思路

  用队列和栈执行给定操作即可。

AC代码

#include
#include
#include
#include
using namespace std;
const int MAXN=1e3+5;
char ch[MAXN];
queue<int> q;
stack<int> s;
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		while(!q.empty()) // 清空队列
			q.pop();
		while(!s.empty()) // 清空栈
			s.pop();
		int n;
		scanf("%d%s",&n,&ch);
		if(ch[2]=='F') //FIFO
		{
			for(int i=0;i<n;i++) // n条命令
			{
				scanf("%s",&ch); 
				if(ch[0]=='I') // IN
				{
					int m;
					scanf("%d",&m);
					q.push(m); // 入队列
				}
				else // OUT
				{ 
					if(q.empty()) // 如果队列为空
						printf("None\n");
					else
					{
						printf("%d\n",q.front()); // 输出
						q.pop(); // 出队列
					}
				}
			}
		}
		else //FILO
		{
			for(int i=0;i<n;i++) // n条命令
			{
				scanf("%s",&ch);
				if(ch[0]=='I') // IN
				{
					int m;
					scanf("%d",&m);
					s.push(m); // 入栈
				}
				else // OUT
				{
					if(s.empty()) // 栈为空
						printf("None\n");
					else
					{
						printf("%d\n",s.top()); // 输出
						s.pop(); //出栈
					}
				}
			}
		}
	}
	return 0;
}

HDU1873 看病要排队【优先队列+自定义比较规则】

传送门:HDU1873 看病要排队

题目描述

乐师-理工ACM暑假集训-STL容器_第4张图片

测试样例

Sample Input
7
IN 1 1
IN 1 2
OUT 1
OUT 2
IN 2 1
OUT 2
OUT 1
2
IN 1 1
OUT 1

Sample Output
2
EMPTY
3
1
1

解题思路

  用三个优先队列来模拟三个医生,执行相应操作即可。
  注意: 如果遇到两个优先权一样的病人的话,则选择最早来排队的病人。所以要自定义优先队列比较规则。

AC代码1

#include
#include
#include
using namespace std;
const int MAXN=1e3+5;
char s[MAXN];
int cnt=0;
struct patient{    
    int priority;    
    int id; 
	patient(int x,int y) //构造
	{
		priority=x;
		id=y;
	}
    friend bool operator < (patient a, patient b) // 重载运算符,自定义比较规则 
    {    
		if(a.priority==b.priority) // 优先级相同,id小的优先,即先来的优先
			return a.id>b.id;
		else
			return a.priority < b.priority; // 优先级不同,优先级高的优先   
    }    
};    
priority_queue<patient> q1; // 1号医生
priority_queue<patient> q2; // 2号医生
priority_queue<patient> q3; // 3号医生
int main()
{
	int n;
	while(~scanf("%d",&n)) // 多组测试 
	{
		while(!q1.empty())
			q1.pop();
		while(!q2.empty())
			q2.pop();
		while(!q3.empty())
			q3.pop();
		id=0;
		while(n--) // n个事件
		{
			scanf("%s",&s);
			if(s[0]=='I') // IN
			{
				int a,b;
				scanf("%d%d",&a,&b); // 挂号医生a,优先级为b
				id++; // "IN A B"事件发生第K次时,进来的病人ID即为K
				if(a==1)
					q1.push(patient(b,id));
				else if(a==2)
					q2.push(patient(b,id));
				else
					q3.push(patient(b,id));
			}
			else // OUT
			{
				int a;
				scanf("%d",&a);
				if(a==1)
				{
					if(q1.empty())
						printf("EMPTY\n");
					else
					{
						printf("%d\n",q1.top().id);
						q1.pop();	
					}
				}
				else if(a==2)
				{
					if(q2.empty())
						printf("EMPTY\n");
					else
					{
						printf("%d\n",q2.top().id);
						q2.pop();	
					}
				}
				else
				{
					if(q3.empty())
						printf("EMPTY\n");
					else
					{
						printf("%d\n",q3.top().id);
						q3.pop();	
					}
				}
			}	
		}
	}
	return 0;
}

AC代码1简化版【优先队列数组】

朋友提供的思路:优先队列数组版

#include
#include
using namespace std;
const int MAXN=1e3+5;
char s[MAXN];
int id=0;
typedef pair<int,int> P; //first存优先级,second存id
struct cmp{
	bool operator () (P p1,P p2)
	{
		if(p1.first==p2.first)	
			return p1.second>p2.second; // 按id从小到大排序
		else
			return p1.first<p2.first; //从优先级从大到小排序
	} 
}; 
priority_queue<P,vector<P>,cmp> q[4]; // 医生
int main()
{
	int n;
	while(~scanf("%d",&n)) // 多组测试 
	{
		// 清空队列
		for(int i=1;i<=3;i++)
			while(!q[i].empty())
				q[i].pop();
		id=0;
		while(n--) // n个事件
		{
			scanf("%s",&s);
			if(s[0]=='I') // IN
			{
				int a,b;
				scanf("%d%d",&a,&b); // 挂号医生a,优先级为b
				id++; // "IN A B"事件发生第K次时,进来的病人ID即为K
				q[a].push(P(b,id));
			}
			else // OUT
			{
				int a;
				scanf("%d",&a);
				if(q[a].empty())
					printf("EMPTY\n");
				else
				{
					printf("%d\n",q[a].top().second);
					q[a].pop();	
				}
			}	
		}
	}
	return 0;
}

HDU2648 Shopping【map】

传送门:HDU2648 Shopping

题目描述

乐师-理工ACM暑假集训-STL容器_第5张图片

测试样例

Sample Input
3
memory
kfc
wind
2
49 memory
49 kfc
48 wind
80 kfc
85 wind
83 memory

Sample Output
1
2

题目大意

  给定一个n和n个商店,然后给定一个m,在接下来的m天,每天n个商店价格会上涨s(注意是上涨s,不是上涨到s),问每天结束,"memory"这家商店排名是多少,这里的排名定义为比它价格高的商店个数+1。

解题思路

  利用map键唯一的特性,累计同一商店的价格,最后遍历map,统计价格大于"memory"的商店个数即可。
  注意:本题描述并未说明是多组测试样例,但是不写while(cin>>n)对多组样例进行处理会WA。

AC代码

#include
#include
#include
#include
#include
#include
using namespace std;
map<string,int> mp;
int main()
{
	int n;
	while(cin>>n) //多组样例,cin不用判断读到文件末尾
	{
		for(int i=0;i<n;i++) // n家商店
		{
			string store;
			cin>>store;
			mp[store]=0; 
		}
		int m;
		cin>>m; 
		for(int i=0;i<m;i++) // m天
		{
			for(int j=0;j<n;j++) // n家商店
			{
				int price;
				string store;
				cin>>price>>store;
				mp[store]+=price; // 商店价格上涨price
			}
			int ans=0,num=mp["memory"];
			map<string,int>::iterator it;
			for(it=mp.begin();it!=mp.end();it++) //遍历n家商店
				if(it->second>num) // 统计价格高于"memory"商店的个数
					ans++;
			cout<<ans+1<<"\n";
		}
		mp.clear(); //清空map
	}
	return 0;
}

你可能感兴趣的:(2020暑假集训)