P1540 [NOIP 2010 提高组] 机器翻译
提交答案加入题单复制题目
题目背景
NOIP2010 提高组 T1
题目描述
小晨的电脑上安装了一个机器翻译软件,他经常用这个软件来翻译英语文章。
这个翻译软件的原理很简单,它只是从头到尾,依次将每个英文单词用对应的中文含义来替换。对于每个英文单词,软件会先在内存中查找这个单词的中文含义,如果内存中有,软件就会用它进行翻译;如果内存中没有,软件就会在外存中的词典内查找,查出单词的中文含义然后翻译,并将这个单词和译义放入内存,以备后续的查找和翻译。
假设内存中有 M 个单元,每单元能存放一个单词和译义。每当软件将一个新单词存入内存前,如果当前内存中已存入的单词数不超过 M−1,软件会将新单词存入一个未使用的内存单元;若内存中已存入 M 个单词,软件会清空最早进入内存的那个单词,腾出单元来,存放新单词。
假设一篇英语文章的长度为 N 个单词。给定这篇待译文章,翻译软件需要去外存查找多少次词典?假设在翻译开始前,内存中没有任何单词。
输入格式
共 2 行。每行中两个数之间用一个空格隔开。
第一行为两个正整数 M,N,代表内存容量和文章的长度。
第二行为 N 个非负整数,按照文章的顺序,每个数(大小不超过 1000)代表一个英文单词。文章中两个单词是同一个单词,当且仅当它们对应的非负整数相同。
输出格式
一个整数,为软件需要查词典的次数。
输入输出样例
输入 #1复制
3 7
1 2 1 5 4 4 1
输出 #1复制
5
说明/提示
样例解释
整个查字典过程如下:每行表示一个单词的翻译,冒号前为本次翻译后的内存状况:
1:查找单词 1 并调入内存。1 2:查找单词 2 并调入内存。1 2:在内存中找到单词 1。1 2 5:查找单词 5 并调入内存。2 5 4:查找单词 4 并调入内存替代单词 1。2 5 4:在内存中找到单词 4。5 4 1:查找单词 1 并调入内存替代单词 2。
共计查了 5 次词典。
数据范围
对于 10% 的数据有 M=1,N≤5对于 100% 的数据有 1≤M≤100,1≤N≤1000。
实现代码:
cpp
#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
int n,m,x,ans,l,r,a[1005],b[1005];
int main()
{
cin>>m>>n;
l=0;r=0;
for (int i=1;i<=n;i++)
{
scanf("%d",&x);
if (a[x]==0)
{
ans++;
r++;b[r]=x;a[x]=1;
if (r>m) {l++;a[b[l]]=0;}
}
}
cout<<ans;
return 0;
}
P2058 [NOIP 2016 普及组] 海港
题目背景
NOIP2016 普及组 T3
题目描述
小 K 是一个海港的海关工作人员,每天都有许多船只到达海港,船上通常有很多来自不同国家的乘客。
小 K 对这些到达海港的船只非常感兴趣,他按照时间记录下了到达海港的每一艘船只情况;对于第 i 艘到达的船,他记录了这艘船到达的时间 ti (单位:秒),船上的乘客数 ki,以及每名乘客的国籍 xi,1,xi,2,...,xi,k。
小K统计了 n 艘船的信息,希望你帮忙计算出以每一艘船到达时间为止的 24 小时(24 小时 =86400 秒)内所有乘船到达的乘客来自多少个不同的国家。
形式化地讲,你需要计算 n 条信息。对于输出的第 i 条信息,你需要统计满足 ti−86400<tp≤ti 的船只 p,在所有的 xp,j 中,总共有多少个不同的数。
输入格式
第一行输入一个正整数 n,表示小 K 统计了 n 艘船的信息。
接下来 n 行,每行描述一艘船的信息:前两个整数 ti 和 ki 分别表示这艘船到达海港的时间和船上的乘客数量,接下来 ki 个整数 xi,j 表示船上乘客的国籍。
保证输入的 ti 是递增的,单位是秒;表示从小K第一次上班开始计时,这艘船在第 ti 秒到达海港。
保证 1≤n≤105,∑ki≤3×105 ,1≤xi,j≤105, 1≤ti−1≤ti≤109。
其中 ∑ki 表示所有的 ki 的和。
输出格式
输出 n 行,第 i 行输出一个整数表示第 i 艘船到达后的统计信息。
输入输出样例
输入 #1复制
3
1 4 4 1 2 2
2 2 2 3
10 1 3
输出 #1复制
3
4
4
输入 #2复制
4
1 4 1 2 2 3
3 2 2 3
86401 2 3 4
86402 1 5
输出 #2复制
3
3
3
4
说明/提示
【样例解释 1】
第一艘船在第 1 秒到达海港,最近 24 小时到达的船是第一艘船,共有 4 个乘客,分别是来自国家 4,1,2,2,共来自 3 个不同的国家;
第二艘船在第 2 秒到达海港,最近 24 小时到达的船是第一艘船和第二艘船,共有 4+2=6 个乘客,分别是来自国家 4,1,2,2,2,3,共来自 4 个不同的国家;
第三艘船在第 10 秒到达海港,最近 24 小时到达的船是第一艘船、第二艘船和第三艘船,共有 4+2+1=7 个乘客,分别是来自国家 4,1,2,2,2,3,3,共来自 4 个不同的国家。
【样例解释 2】
第一艘船在第 1 秒到达海港,最近 24 小时到达的船是第一艘船,共有 4 个乘客,分别是来自国家 1,2,2,3,共来自 3 个不同的国家。
第二艘船在第 3 秒到达海港,最近 24 小时到达的船是第一艘船和第二艘船,共有 4+2=6 个乘客,分别是来自国家 1,2,2,3,2,3,共来自 3 个不同的国家。
第三艘船在第 86401 秒到达海港,最近 24 小时到达的船是第二艘船和第三艘船,共有 2+2=4 个乘客,分别是来自国家 2,3,3,4,共来自 3 个不同的国家。
第四艘船在第 86402 秒到达海港,最近 24 小时到达的船是第二艘船、第三艘船和第四艘船,共有 2+2+1=5 个乘客,分别是来自国家 2,3,3,4,5,共来自 4个 不同的国家。
【数据范围】
- 对于 10% 的测试点,n=1,∑ki≤10,1≤xi,j≤10,1≤ti≤10。
- 对于 20% 的测试点,1≤n≤10,∑ki≤100,1≤xi,j≤100,1≤ti≤32767。
- 对于 40% 的测试点,1≤n≤100,∑ki≤100,1≤xi,j≤100,1≤ti≤86400。
- 对于 70% 的测试点,1≤n≤1000,∑ki≤3000,1≤xi,j≤1000,1≤ti≤109。
- 对于 100% 的测试点,1≤n≤105,∑ki≤3×105,1≤xi,j≤105,1≤ti≤109
实现代码:
cpp
#include <bits/stdc++.h>
#define ll long long
using namespace std;
struct node
{
int timee,country;
}q[300005];
int cnt[100005],ans;
int head,tail;
int main()
{
int T;
cin>>T;
while(T--)
{
int t,k;
cin>>t>>k;
for(int i=1;i<=k;i++)
{
int x;
cin>>x;
q[++tail]={t,x};
cnt[x]++;
if(cnt[x]==1) ans++;
}
while(head<tail&&t-q[head].timee>=86400)
{
cnt[q[head].country]--;
if(cnt[q[head].country]==0) ans--;
head++;
}
cout<<ans<<'\n';
}
return 0;
}
P1241 括号序列
题目描述
定义如下规则:
- 空串是「平衡括号序列」
- 若字符串 S 是「平衡括号序列」,那么 [S] 和 (S) 也都是「平衡括号序列」
- 若字符串 A 和 B 都是「平衡括号序列」,那么 AB(两字符串拼接起来)也是「平衡括号序列」。
例如,下面的字符串都是平衡括号序列:
(),[],(()),([]),()[],()[()]
而以下几个则不是:
(,[,],)(,()),([()
现在,给定一个仅由 (,),[,]构成的字符串 s,请你按照如下的方式给字符串中每个字符配对:
- 从左到右扫描整个字符串。
- 对于当前的字符,如果它是一个右括号,考察它与它左侧离它最近 的未匹配的的左括号。如果该括号与之对应(即小括号匹配小括号,中括号匹配中括号),则将二者配对。如果左侧未匹配的左括号不存在或与之不对应,则其配对失败。
配对结束后,对于 s 中全部未配对的括号,请你在其旁边添加一个字符,使得该括号和新加的括号匹配。
输入格式
输入只有一行一个字符串,表示 s。
输出格式
输出一行一个字符串表示你的答案。
输入输出样例
输入 #1复制
([()
输出 #1复制
()[]()
输入 #2复制
([)
输出 #2复制
()[]()
说明/提示
数据规模与约定
对于全部的测试点,保证 s 的长度不超过 100,且只含 (,),[,] 四种字符。
实现代码:
cpp
#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
int top,w[110];
string a;
char s[110],c[110];
int main()
{
// freopen("work.in","r",stdin);freopen("work.out","w",stdout);
cin >> a;
int n=a.length();
for(int i=0;i<n;i++)
{
if(a[i] == '(' || a[i] == '[')
{
s[++top]=a[i];
w[top]=i;
if(a[i] == '(') c[i]=')';
else c[i]=']';
}
if(a[i] == ')')
{
if(top && s[top] == '(') {c[w[top]]=' '; top--;}
else c[i]='(';
}
if(a[i] == ']')
{
if(top && s[top] == '[') {c[w[top]]=' '; top--;}
else c[i]='[';
}
}
for(int i=0;i<n;i++)
{
if(c[i] == '(' || c[i] == '[') printf("%c%c",c[i],a[i]);
else if(c[i] == ')' || c[i] == ']') printf("%c%c",a[i],c[i]);
else printf("%c",a[i]);
}
// fclose(stdin);fclose(stdout);
return 0;
}
P4387 【深基15.习9】验证栈序列
提交答案加入题单复制题目
题目描述
给出两个序列 pushed 和 poped 两个序列,其取值从 1 到 n(n≤100000)。已知入栈序列是 pushed,如果出栈序列有可能是 poped,则输出 Yes,否则输出 No。请注意,给定的序列一定是一个排列(即没有重复数字)。
为了防止骗分,每个测试点有多组数据,不超过 5 组。
输入格式
第一行一个整数 q,询问次数。
接下来 q 个询问,对于每个询问:
第一行一个整数 n 表示序列长度;
第二行 n 个整数表示入栈序列;
第三行 n 个整数表示出栈序列;
输出格式
对于每个询问输出答案。
输入输出样例
输入 #1复制
2
5
1 2 3 4 5
5 4 3 2 1
4
1 2 3 4
2 4 1 3
输出 #1复制
Yes
No
实现代码:
cpp
#include<iostream>
#include<stack>
using namespace std;
stack<int>q;
int p,n;
int main()
{
cin>>p;
while(p--)
{
cin>>n;
int a[n+1],b[n+1],sum=1;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
cin>>b[i];
for(int i=1;i<=n;i++)
{
q.push(a[i]);
while((q.top())==b[sum])
{
q.pop(),sum++;
if(q.empty())break;
}
}
if(q.empty()) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
while(!q.empty())q.pop();
}
return 0;
}
P2234 [HNOI2002] 营业额统计
题目描述
Tiger 最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。
Tiger 拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况:当最小波动值越大时,就说明营业情况越不稳定。
而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助 Tiger 来计算这一个值。
我们定义,一天的最小波动值 = min{∣该天以前某一天的营业额−该天营业额∣}。
特别地,第一天的最小波动值为第一天的营业额。
输入格式
第一行为正整数 n(n≤32767) ,表示该公司从成立一直到现在的天数,接下来的 n 行每行有一个整数 ai(∣ai∣≤106) ,表示第 i 天公司的营业额,可能存在负数。
输出格式
输出一个整数,即每一天最小波动值的和,保证结果小于 231。
输入输出样例
输入 #1复制
6
5
1
2
5
4
6
输出 #1复制
12
说明/提示
结果说明:5+∣1−5∣+∣2−1∣+∣5−5∣+∣4−5∣+∣6−5∣=5+4+1+0+1+1=12
实现代码:
cpp
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<set>
using namespace std;
set<int>s;
set<int>::iterator k,a;
int n,x,ans=0;
int main()
{
s.insert(192608170);
s.insert(-192608170);
scanf("%d",&n);
for(register int i=1;i<=n;++i)
{
scanf("%d",&x);
if(s.size()==2)
{
ans+=x;
s.insert(x);
}
else
{
k=s.lower_bound(x);
if(*k!=x)
{
a=k;
a--;
ans+=min(abs(*a-x),abs(*k-x));
s.insert(x);
}
}
}
printf("%d\n",ans);
return 0;
}