并查集卡了好久沒時間,最后一題蹭了5%
第一題
題意
兩個降序鏈表求相同的部分,
分析
不想寫鏈表就直接陣列了,直接搞個map就行了,
參考代碼
#include <cstdio>
#include <iostream>
#include <map>
using namespace std;
const int MAXN = 1000005;
int n, m;
int a[MAXN], b[MAXN];
map<int, int> Map;
int main() {
scanf("%d", &n);
for (int i=1; i<=n; ++i) {
scanf("%d", &a[i]);
Map[a[i]] = 1;
}
scanf("%d", &m);
for (int i=1; i<=m; ++i) {
scanf("%d", &b[i]);
if (Map.count(b[i])) {
printf("%d ", b[i]);
}
}
printf("\n");
return 0;
}
第二題
題意
有n個人編號可能會出現0-n里面的數字,m個小組,有一個事情會告訴0號,然后0號會告訴他們小組的其他人,然后其他人在告訴有他們的小組的其他人,然后問最后有多少人知道這個事情,
分析
經典并查集,一直20%,最后發現編號是0 ~ n,不是0 ~ n-1,,,,
據說是改了題目?實在是太坑了,卡了我至少半個小時,
參考代碼
#include <cstdio>
#include <iostream>
using namespace std;
int fa[1000005];
int t[10005];
int n, m;
inline int find(int x) {
if (fa[x] == x) return x;
else return fa[x] = find(fa[x]);
}
inline void combine(int x, int y) {
int fx = find(x), fy = find(y);
if (fx==fy) return;
fa[fx] = fy;
}
int main() {
while(cin >> n >> m) {
for (int i=0; i<=n; ++i) {
fa[i] = i;
}
for (int i=0; i<m; ++i) {
int x;
scanf("%d", &x);
for (int j=0; j<x; ++j) {
scanf("%d", &t[j]);
if (j!=0) combine(t[j], t[j-1]);
}
}
int ans = 0;
for (int i=0; i<=n; ++i) {
if (find(i) == find(0)) {
ans++;
}
}
printf("%d\n", ans);
}
return 0;
}
第三題
題意
給n個字串,根據字串出現次數排序,求前k個出現次數最多的,和前k個出現次數最少的,如果出現次數一樣,都按照字典序排列,
樣例輸入:
4 2
1
2
3
4
樣例輸出:
1 1
2 1
1 1
2 1
分析
直接寫兩個排序,排完輸出就完事了,
參考代碼
#include <cstdio>
#include <iostream>
#include <string>
#include <algorithm>
#include <unordered_map>
using namespace std;
int n, k;
unordered_map<string, int> M;
struct node {
string str;
int num;
};
string a[100005];
node b[100005];
bool cmp1(node x, node y) {
if (x.num == y.num) return x.str < y.str;
return x.num > y.num;
}
bool cmp2(node x, node y) {
if (x.num == y.num) return x.str < y.str;
return x.num < y.num;
}
int main() {
scanf("%d%d", &n, &k);
for (int i=1; i<=n; ++i) {
cin >> a[i];
M[a[i]]++;
}
int sum = 0;
for (int i=1; i<=n; ++i) {
if (M[a[i]] != -1) {
++sum;
b[sum].str = a[i];
b[sum].num = M[a[i]];
M[a[i]] = -1;
}
}
sort(b+1, b+1+sum, cmp1);
for (int i=1; i<=k; ++i) {
cout << b[i].str << " " << b[i].num << endl;
}
sort(b+1, b+1+sum, cmp2);
for (int i=1; i<=k; ++i) {
cout << b[i].str << " " << b[i].num << endl;
}
return 0;
}
第四題
題意
給一個偶數長度的序列,求洗掉其中每一個數之后的中位數各是多少,
樣例輸入:
6
1 2 3 4 5 6
樣例輸出:
4
4
4
3
3
3
分析
顯然如果是排序好的序列,前半部分洗掉之后的中位數就是第n/2+1位,后半部分就是n/2位,如樣例,
因此可以先記錄每個數的位置,然后按照大小排序,然后得到中位數之后,再重新按照位置排序輸出結果即可,
參考代碼
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
int n, x;
struct node {
int id, val, ans;
};
node a[200005];
bool cmp1(node x, node y) {
return x.val < y.val;
}
bool cmp2(node x, node y) {
return x.id < y.id;
}
int main() {
scanf("%d", &n);
for (int i=1; i<=n; ++i) {
scanf("%d", &a[i].val);
a[i].id = i;
}
// 大小排序
sort(a+1, a+1+n, cmp1);
// 求中位數
for (int i=1; i<=n/2; ++i) {
a[i].ans = a[n/2+1].val;
}
for (int i=n/2+1; i<=n; ++i) {
a[i].ans = a[n/2].val;
}
// 序號排序
sort(a+1, a+1+n, cmp2);
for (int i=1; i<=n; ++i) {
printf("%d\n", a[i].ans);
}
return 0;
}
第五題
題意
有兩個顏色紅和黑,每種顏色各有n個數字,給一個帶顏色的數字序列,可以相鄰交換,要求最后數字序列相同顏色的數字要升序,求最少的次數,
分析
因為n很小,寫了個n方的做法,但是不對,等一手其他人的做法,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/1479.html
標籤:區塊鏈
上一篇:PTA 狼人殺-簡單版(c++)
