门禁系统
描述
问题描述
涛涛最近要负责图书馆的管理工作,需要记录下每天读者的到访情况。每位读者有一个编号,每条记录用读者的编号来表示。给出读者的来访记录,请问每一条记录中的读者是第几次出现。
输入格式
输入的第一行包含一个整数n,表示涛涛的记录条数。
第二行包含n个整数,依次表示涛涛的记录中每位读者的编号。
输出格式
输出一行,包含n个整数,由空格分隔,依次表示每条记录中的读者编号是第几次出现。
样例输入
5
1 2 1 1 3
样例输出
1 1 2 3 1
评测用例规模与约定
1≤n≤1,000,读者的编号为不超过n的正整数。
分析
开一个数组用哈希的思想来记录就好了,数据范围也不大,数组完全ok
代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
int coun[1005];
int main()
{
int n;
while(~scanf("%d",&n))
{
for(int i = 0;i<=n;i++)coun[i] = 0;
int x ;
for(int i = 1;i<=n;i++)
{
scanf("%d",&x);
coun[x]++;
cout<<coun[x]<<" ";
}
cout<<"\n";
}
}
Z字形扫描
描述
问题描述
在图像编码的算法中,需要将一个给定的方形矩阵进行Z字形扫描(Zigzag Scan)。给定一个n×n的矩阵,Z字形扫描的过程如下图所示:
对于下面的4×4的矩阵,
1 5 3 9
3 7 5 6
9 4 6 4
7 3 1 3
对其进行Z字形扫描后得到长度为16的序列:
1 5 3 9 7 3 9 5 4 7 3 6 6 4 1 3
请实现一个Z字形扫描的程序,给定一个n×n的矩阵,输出对这个矩阵进行Z字形扫描的结果。
输入格式
输入的第一行包含一个整数n,表示矩阵的大小。
输入的第二行到第n+1行每行包含n个正整数,由空格分隔,表示给定的矩阵。
输出格式
输出一行,包含n×n个整数,由空格分隔,表示输入的矩阵经过Z字形扫描后的结果。
样例输入
4
1 5 3 9
3 7 5 6
9 4 6 4
7 3 1 3
样例输出
1 5 3 9 7 3 9 5 4 7 3 6 6 4 1 3
评测用例规模与约定
1≤n≤500,矩阵元素为不超过1000的正整数。
分析
比较常见的题,找到规律就可以了。按照z的周期来
代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
int ku[503][503];
int main()
{
int n;
while(~scanf("%d",&n))
{
for(int i = 1;i<=n;i++)
for(int j = 1;j<=n;j++)
scanf("%d",&ku[i][j]);
int i = 1,j = 1;
cout<<ku[i][j]<<" ";
while(i<n || j<n)
{
if(j+1<=n)j++;
else i++;
cout<<ku[i][j]<<" ";
while(j>1 && i<n)
{
i++;j--;
cout<<ku[i][j]<<" ";
}
if(i+1<=n)i++;
else j++;
cout<<ku[i][j]<<" ";
while(j<n && i>1)
{
i--;j++;
cout<<ku[i][j]<<" ";
}
}
cout<<"\n";
}
}
画图
描述
问题描述
在一个定义了直角坐标系的纸上,画一个(x1,y1)到(x2,y2)的矩形指将横坐标范围从x1到x2,纵坐标范围从y1到y2之间的区域涂上颜色。
下图给出了一个画了两个矩形的例子。第一个矩形是(1,1) 到(4, 4),用绿色和紫色表示。第二个矩形是(2, 3)到(6, 5),用蓝色和紫色表示。图中,一共有15个单位的面积被涂上颜色,其中紫色部分被涂了两次,但在计算面积时只计算一次。在实际的涂色过程中,所有的矩形都涂成统一的颜色,图中显示不同颜色仅为说明方便。
给出所有要画的矩形,请问总共有多少个单位的面积被涂上颜色。
输入格式
输入的第一行包含一个整数n,表示要画的矩形的个数。
接下来n行,每行4个非负整数,分别表示要画的矩形的左下角的横坐标与纵坐标,以及右上角的横坐标与纵坐标。
输出格式
输出一个整数,表示有多少个单位的面积被涂上颜色。
样例输入
2
1 1 4 4
2 3 6 5
样例输出
15
评测用例规模与约定
1<=n<=100,0<=横坐标、纵坐标<=100。
分析
数据量不大,所以直接计数就好了
以area[i][j]表示以(i,j)为左下角顶点的单位为1的小格子,初始全是0,在范围内的就标1并且计数,最后输出结果
代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
int area[105][105];
int main()
{
int n;
while(~scanf("%d",&n))
{
int sum = 0;
int x1,y1,x2,y2;
for(int i = 0;i<=n;i++)
for(int j = 0;j<=n;j++)
area[i][j] = 0;
for(int i =0;i<n;i++)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
for(int s = x1;s<x2;s++)
for(int e = y1;e<y2;e++)
{
if(area[s][e]==0)
{
area[s][e] = 1; sum ++;
}
}
}
cout<<sum<<"\n";
}
}
字符串匹配
描述
问题描述
给出一个字符串和多行文字,在这些文字中找到字符串出现的那些行。你的程序还需支持大小写敏感选项:当选项打开时,表示同一个字母的大写和小写看作不同的字符;当选项关闭时,表示同一个字母的大写和小写看作相同的字符。
输入格式
输入的第一行包含一个字符串S,由大小写英文字母组成。
第二行包含一个数字,表示大小写敏感的选项,当数字为0时表示大小写不敏感,当数字为1时表示大小写敏感。
第三行包含一个整数n,表示给出的文字的行数。
接下来n行,每行包含一个字符串,字符串由大小写英文字母组成,不含空格和其他字符。
输出格式
输出多行,每行包含一个字符串,按出现的顺序依次给出那些包含了字符串S的行。
样例输入
Hello
1
5
HelloWorld
HiHiHelloHiHi
GrepIsAGreatTool
HELLO
HELLOisNOTHello
样例输出
HelloWorld
HiHiHelloHiHi
HELLOisNOTHello
样例说明
在上面的样例中,第四个字符串虽然也是Hello,但是大小写不正确。如果将输入的第二行改为0,则第四个字符串应该输出。
评测用例规模与约定
1<=n<=100,每个字符串的长度不超过100。
分析
这里主要用了c++ string里的find()函数
string :: size_type position = s.find(s2);
if position != s.npos就是找到了
然后在大小写不敏感的时候全部转化成小写来匹配
代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
string strs[105];
string little[105];
int main()
{
string input;
while(cin>>input)
{
int opt,n;
scanf("%d%d",&opt,&n);
for(int i = 0;i<n;i++)
{
cin>>strs[i];
for(int j = 0;j<strs[i].length();j++)
little[i] += tolower(strs[i][j]);
}
string::size_type position;
if(opt == 0)
{
transform(input.begin(),input.end(),input.begin(),::tolower);
for(int i = 0;i<n;i++)
{
position = little[i].find(input);
if(position != little[i].npos)cout<<strs[i]<<"\n";
}
}
else{
for(int i = 0;i<n;i++)
{
position = strs[i].find(input);
if(position != strs[i].npos)cout<<strs[i]<<"\n";
}
}
}
}
相反数
描述
问题描述
有 N 个非零且各不相同的整数。请你编一个程序求出它们中有多少对相反数(a 和 -a 为一对相反数)。
输入格式
第一行包含一个正整数 N。(1 ≤ N ≤ 500)。
第二行为 N 个用单个空格隔开的非零整数,每个数的绝对值不超过1000,保证这些整数各不相同。
输出格式
只输出一个整数,即这 N 个数中包含多少对相反数。
样例输入
5
1 2 3 -1 -2
样例输出
2
分析
比较简单,数量级也不大,排序后一个从头开始找负数,另一个从后开始找有没有对应的正数
代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
int neg[505],pos[505];
bool binSearch(int x,int n)
{
int goal = -x;
int begin = 0,end = n-1,mid;
while(begin<=end)
{
mid = (begin+end)/2;
if(pos[mid]==goal)return true;
else if(pos[mid]<goal)
{
begin = mid + 1;
}
else end = mid-1;
}
return false;
}
int main()
{
int n;
while(~scanf("%d",&n))
{
for(int i=0;i<n;i++)
scanf("%d",&neg[i]);
sort(neg,neg+n);
int i = 0,j = n-1;
int ans = 0;
while(neg[i]<=0)
{
for(j = n-1;neg[j]>0;j--)
if(neg[j]==-neg[i])ans ++;
i++;
}
cout<<ans<<"\n";
}
}
窗口
描述
问题描述
在某图形操作系统中,有 N 个窗口,每个窗口都是一个两边与坐标轴分别平行的矩形区域。窗口的边界上的点也属于该窗口。窗口之间有层次的区别,在多于一个窗口重叠的区域里,只会显示位于顶层的窗口里的内容。
当你点击屏幕上一个点的时候,你就选择了处于被点击位置的最顶层窗口,并且这个窗口就会被移到所有窗口的最顶层,而剩余的窗口的层次顺序不变。如果你点击的位置不属于任何窗口,则系统会忽略你这次点击。
现在我们希望你写一个程序模拟点击窗口的过程。
输入格式
输入的第一行有两个正整数,即 N 和 M。(1 ≤ N ≤ 10,1 ≤ M ≤ 10)
接下来 N 行按照从最下层到最顶层的顺序给出 N 个窗口的位置。 每行包含四个非负整数 x1, y1, x2, y2,表示该窗口的一对顶点坐标分别为 (x1, y1) 和 (x2, y2)。保证 x1 < x2,y1 2。
接下来 M 行每行包含两个非负整数 x, y,表示一次鼠标点击的坐标。
题目中涉及到的所有点和矩形的顶点的 x, y 坐标分别不超过 2559 和 1439。
输出格式
输出包括 M 行,每一行表示一次鼠标点击的结果。如果该次鼠标点击选择了一个窗口,则输出这个窗口的编号(窗口按照输入中的顺序从 1 编号到 N);如果没有,则输出”IGNORED”(不含双引号)。
样例输入
3 4
0 0 4 4
1 1 5 5
2 2 6 6
1 1
0 0
4 4
0 5
样例输出
2
1
1
IGNORED
样例说明
第一次点击的位置同时属于第 1 和第 2 个窗口,但是由于第 2 个窗口在上面,它被选择并且被置于顶层。
第二次点击的位置只属于第 1 个窗口,因此该次点击选择了此窗口并将其置于顶层。现在的三个窗口的层次关系与初始状态恰好相反了。
第三次点击的位置同时属于三个窗口的范围,但是由于现在第 1 个窗口处于顶层,它被选择。
最后点击的 (0, 5) 不属于任何窗口。
分析
输入给定的是从底到最顶层,所以想到了用栈来处理,这样可以从上往下检查,只要点的坐标在两个顶点坐标内就可以,上面的弹出后先依次存到另一个栈里,这样查找一遍后从栈2中依次pop 出来push到原栈里,顺序就还是一样的
最后若有选中的,就把选中的加到最顶层
注意这个序号是按输入顺序,而不是顶层为1
代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<vector>
#include<stack>
using namespace std;
struct window{
int x1,x2,y1,y2;
int id;
};
stack<window>w1;
stack<window>w2;
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
for(int i =0;i<n;i++)
{
window w;
scanf("%d %d %d %d",&w.x1,&w.y1,&w.x2,&w.y2);
w.id = (i+1);
w1.push(w);
}
for(int i=0;i<m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
bool flag = false;
window top;
while(!w1.empty())
{
top = w1.top();
window newtop;
if(x>=top.x1 && x<=top.x2 && y>=top.y1 && y<=top.y2)
{
printf("%d\n",top.id);
flag = true;
newtop = top;
w1.pop();
break;
}
else{
w1.pop();
w2.push(top);
}
}
while(!w2.empty())
{
window w2top = w2.top();
w1.push(w2top);
w2.pop();
}
if(flag==false)
{
printf("IGNORED\n");
}
else
{
w1.push(top);
}
}
}
}