傳送門
A.
模擬。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 7;
int main() {
string a, b, c;
cin >> a >> b >> c;
if(a == "<") {
if(c == "<") cout << "B" << endl;
else {
if(b == "<") cout << "C" << endl;
else cout << "A" << endl;
}
}
else {
if(b == "<") cout << "A" << endl;
else {
if(c == "<") cout << "C" << endl;
else cout << "B" << endl;
}
}
return 0;
}
B.
模擬。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 7;
int vis[N];
int main() {
int n, m;
cin >> n >> m;
for(int i = 1; i <= m; i ++) {
int a;
string b;
cin >> a >> b;
if(b == "F") {
cout << "No" << endl;
}
else {
if(!vis[a]) {
cout << "Yes" << endl;
vis[a] = 1;
}
else cout << "No" << endl;
}
}
return 0;
}
C.
題意為,給兩個無向圖 \(M_G, M_H\),每次可以選 \(M_H\) 的兩點 \(i, j\),刪去這條邊或加上這條邊,花費 \(a_{i,j}\),問最少花費多少使得兩個圖同構。
注意到 \(n \le 8\),可以對 \(M_G\) 全排列,然後 \(n^2\) 更新最小值,時間複雜度 \(O(n!n^2)\)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 200;
vector<int> g1[N], g2[N];
int a[N][N];
int p1[N][N], p2[N][N];
int pp[N];
signed main() {
int n, m1, m2;
cin >> n >> m1;
for(int i = 1; i <= m1; i ++) {
int x, y;
cin >> x >> y;
p1[x][y] = 1;
p1[y][x] = 1;
}
cin >> m2;
for(int i = 1; i <= m2; i ++) {
int x, y;
cin >> x >> y;
p2[x][y] = 1;
p2[y][x] = 1;
}
for(int i = 1; i <= n; i ++) {
for(int j = i + 1; j <= n; j ++) {
cin >> a[i][j];
}
}
int cnt = 0x3f3f3f3f;
for(int i = 1; i <= n; i ++) pp[i] = i;
do{
int ans = 0;
for(int i = 1; i <= n; i ++) {
for(int j = i + 1; j <= n; j ++) {
if((p1[pp[i]][pp[j]] && p2[i][j]) || (!p1[pp[i]][pp[j]] && !p2[i][j])) continue;
ans += a[i][j];
}
}
cnt = min(cnt, ans);
}while(next_permutation(pp + 1, pp + n + 1));
cout << cnt << endl;
return 0;
}
D.
有 \(n\) 個村莊,座標 \(x_i\),有 \(p_i\) 人,\(q\) 組詢問,座標 \(l_i, r_i\) 之間有多少人。
\(-10^9 \le x_i \le 10^9\),對 \(n\) 個村莊字首和,二分 \(l_i, r_i\) 的右邊第一個村莊。
#include<bits/stdc++.h>
#define int long long
using namespace std;
struct Village {
int x;
int p;
};
bool compare(const Village &a, const Village &b) {
return a.x < b.x;
}
signed main() {
int n;
cin >> n;
vector<Village> villages(n);
for (int i = 0; i < n; ++i) {
cin >> villages[i].x;
}
for (int i = 0; i < n; ++i) {
cin >> villages[i].p;
}
sort(villages.begin(), villages.end(), compare);
vector<long long> prefix(n + 1, 0);
for (int i = 1; i <= n; ++i) {
prefix[i] = prefix[i - 1] + villages[i - 1].p;
}
int q;
cin >> q;
for (int i = 0; i < q; ++i) {
int L, R;
cin >> L >> R;
int ll = lower_bound(villages.begin(), villages.end(), Village{L, 0}, compare) - villages.begin();
int rr = upper_bound(villages.begin(), villages.end(), Village{R, 0}, compare) - villages.begin() - 1;
if (left <= right) {
cout << prefix[rr + 1] - prefix[ll] << endl;
} else {
cout << 0 << endl;
}
}
return 0;
}
E.
求 \(\sum_{i=1}^{n}\sum_{j=i}^{n} f(i,j)\),\(f(i,j)\) 表示子串 \((s_i, ..., s_j)\) 的字元種類數。
發現加入一個 \(x\),較 \(lst[x]\) 多出了 \((i - lst[x])\) 個區間(可以理解為,區間的左端點個數不變,右端點可選擇的多了 \(i - lst[x]\)),然後按照這個模擬即可。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6 + 7;
int lst[N], ans, a[N], now;
signed main() {
int n;
cin >> n;
for(int i = 1; i <= n; i ++) cin >> a[i];
for(int i = 1; i <= n; i ++) {
now += (i - lst[a[i]]);
ans += now;
lst[a[i]] = i;
}
cout << ans << endl;
}