hihocoder编程练习赛56 A 描述 小Hi的面前摆放了N张卡片,每张卡片都有A和B两面。其中第i张卡片的A面写着一个整数Ai,B面写着一个整数Bi。 一开始所有卡片都是A面向上。现在小Hi必须选择一张卡片,将其翻成B面向上。 设N张卡片向上那一面的数字组成的集合是S,那么游戏的得分是:最小的不属于S的正整数。 例如S={1, 2, 4, 6, 7},则得分是3。 你能算出小Hi最多能得多少分么?
输入 第一行包含一个整数N。 第二行包含N个整数Ai。 第三行包含N个整数Bi。 对于50%的数据,1 ≤ N ≤ 1000 对于100%的数据,1 ≤ N ≤ 100000 1 ≤ Ai, Bi ≤ 1000000
输出 输出最大得分
样例输入 5 1 2 3 5 6 3 4 3 4 4
样例输出 6
参考AC代码 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
using namespace std;
int n;
int a[maxn],b[maxn];
int num[maxn*10];
set <int>s;
int main (){
// freopen("input.txt" ,"r" ,stdin);
scanf("%d" ,&n);
memset(num,0,sizeof num);
for (int i=1;i<=n;i++) scanf("%d" ,&a[i]),num[a[i]]++;
for (int i=1;i<=n;i++) scanf("%d" ,&b[i]);
for (int i=1;i<=1000000;i++){
if (!num[i]) s.insert(i);
}
int ans=0;
for (int i=1;i<=n;i++){
num[a[i]]--;
num[b[i]]++;
s.erase(b[i]);
if (num[a[i]]==0) s.insert(a[i]);
ans=max(ans,*s.begin());
num[a[i]]++;
num[b[i]]--;
s.erase(a[i]);
if (num[b[i]]==0) s.insert(b[i]);
}
cout<<ans<<endl;
return 0;
}
思路 本题相当于要维护一个未出现数字集合的小根堆 并且要满足插入删除操作 联想到set 然后暴力模拟即可
B 描述 小Hi得到了一张藏宝图。图中有一串数字字符串,小Hi分析应该是一处坐标”X,Y”,例如”13.2,20”。 可以由于藏宝图年代久远,标点符号’.’和’,’都消失不见了,只剩下一串数字,例如”13220”。 你能帮助小Hi从数字串还原出所有可能的坐标吗? 合法的X或Y应满足:
是一个整数或小数。
没有多余的0。例如”03”,”0.10”, “00.2”, “1.0”都不合法。
小数点不能在首尾。例如”.2”, “2.”都不合法。
输入 一个数字字符串,长度不超过6。 输入保证有解。
输出 所有可能的坐标,每个一行。 按X从小到大输出;如果X相同,按Y从小到大输出。
样例输入 13220
样例输出 1,3220 1.3,220 1.32,20 1.322,0 13,220 13.2,20 13.22,0 132,20 132.2,0 1322,0
参考AC代码 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
using namespace std;
string s;
vector<pair<double,double> >a;
bool check(string s){
int len=s.length();
int flag=0;
for (int i=0;i<len;i++){
if (s[i]=='.' ){
flag=1;
break ;
}
}
if (len==1) return true ;
if (s[0]=='0' && s[1]!='.' ) return false ;
if (flag && s[len-1]=='0' ) return false ;
if (!flag) return true ;
return true ;
}
void fun(string s1,string s2){
int len1=s1.length();
int len2=s2.length();
for (int i=1;i<=len1;i++){
for (int j=1;j<=len2;j++){
if (i!=len1) s1.insert(i,"." );
if (j!=len2) s2.insert(j,"." );
// cout<<s1<<" " <<s2<<" " <<check(s1)<<" " <<check(s2)<<endl;
if (check(s1) && check(s2)){
double x,y;
if (len1==0 && s1[0]=='0' ) x=0;
else x=atof(s1.c_str());
if (len2==0 && s2[0]=='0' ) y=0;
else y=atof(s2.c_str());
a.push_back(make_pair(x,y));
}
if (i!=len1) s1.erase(i,1);
if (j!=len2) s2.erase(j,1);
}
}
}
int main (){
// freopen("input.txt" ,"r" ,stdin);
cin>>s;
int len=s.length();
for (int i=1;i<len;i++){
string s1=" " ,s2=" " ;
s1=s.substr(0,i);
s2=s.substr(i,len-i);
fun(s1,s2);
}
sort(a.begin(),a.end());
for (int i=0;i<a.size();i++){
cout<<a[i].first<<"," <<a[i].second<<endl;
}
return 0;
}
思路 暴力拆分 每个部分再暴力小数点位置 check后加入pair排序输出 atof实现string转duuble check函数注意先后顺序
C 描述 有N件物品,分别属于很多不同的类别。现在你陆续知道若干对物品的关系,用字母R接一个三元组表示: R X Y 1,表示X和Y属于同一个类别; R X Y 2,表示X和Y属于不同的类别; 同时,你也会被询问某对物品的关系,用字母Q接一个二元组表示: Q X Y,表示询问X和Y的关系。 你需要根据已知的关系推断,如果X和Y属于同一个类别,输出1;如果X和Y属于不同的类别,输出2;如果不确定,输出3。
输入 第一行包含两个整数N和M,N是物种总数,M是以下R和Q指令的总和。 以下N行,每行包含一条指令。 对于50%的数据,1 ≤ N ≤ 1000, 1 ≤ M ≤ 2000 对于100%的数据,1 ≤= N ≤ 100000 1 ≤ M ≤ 200000 1 ≤ X, Y ≤ N 数据保证没有矛盾
输出 对于每一条Q指令,输出1/2/3代表两个物品的关系。
样例输入 6 9 R 1 2 1 R 1 3 1 R 1 4 2 Q 2 4 Q 1 6 R 3 6 1 R 4 5 2 Q 1 5 Q 1
样例输出 2 3 3 1
参考AC代码 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
using namespace std;
int n,m;
int p[maxn];
set <int>s[maxn];
int find(int x){
return x==p[x]?x:p[x]=find(p[x]);
}
void merge(int a,int b){
int x=find(a);
int y=find(b);
if (x!=y){
// if (s[x].size()<s[y].size()) swap(x,y);
for (auto pp:s[y]) s[x].insert(find(pp));
p[y]=x;
}
}
int main (){
// freopen("input.txt" ,"r" ,stdin);
cin>>n>>m;
for (int i=0;i<=n;i++) p[i]=i;
while (m--){
char op;
cin>>op;
if (op=='R' ){
int x,y,z;
scanf("%d%d%d" ,&x,&y,&z);
if (z==1) merge(x,y);
else {
x=find(x),y=find(y);
s[x].insert(y),s[y].insert(x);
}
}
else if (op=='Q' ){
int x,y;
scanf("%d%d" ,&x,&y);
x=find(x),y=find(y);
int ans=0;
if (x==y) ans=1;
else if (s[x].count(y) || s[y].count(x)) ans=2;
else ans=3;
cout<<ans<<endl;
}
}
return 0;
}
思路 并查集相关 基础上再加一个二维set判断不是集合的元素 如果x和y在一个集合里 那么x和所有不和y是一个集合的元素也不在一个集合中 反之同理 处理好merge函数即可 用set模拟 本题启发式合并没有加速很多