abc371
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;
}