题目链接:Educational Codeforces Round 161 (Rated for Div. 2)
PS:A开的很快,B读个假题意,C又想歪了,导致E没时间写,最后十分钟开E思路对了但是没时间了,赛后很快过了。。。
A. Tricky Template
题意:定义模板串 t 与字符串 s :
1:如果模板串的某一项为小写字母,那么模板串与字符串的该项相同
2:如果模板串的某一项为大写字母,那么模板串和字符串的该项不同
如果同时满足以上两个条件,则字符串 s 和模板串 t 匹配成功,求是否存在模板串和给定的 a , b 串匹配,但是不和字符串 c 匹配
解题思路:读题读了一会,做法很简单,只要 c 的某一项满足既不和 a 的该项相同,又不和 b 的该项相同即可
查看代码
void solve(){
int n;
string s1, s2, s3;
cin >> n >> s1 >> s2 >> s3;
for(int i = 0; i < s1.size(); i ++){
if(s3[i] != s2[i] && s3[i] != s1[i]){
cout << "YES\n";
return;
}
}
cout << "NO\n";
}
B. Forming Triangles
题意:有 n 根木棒,每根木棒的长度为 2a[i],求能组成的最多的三角形的数量,三角形的三根木棒顺序不考虑,只考虑是不是同一根(刚开始没看见是2a[i]卡了好久)
解题思路:由于是2a[i]就很好想了,一共两种情况:
1:从同长度的木棒中任选三条,也就是 C(n, 3)
2:从同长度的木棒中任选两条,再从小于本长度的木棒中任选一条
查看代码 void solve(){
cin >> n;
map<int, int> mp;
for(int i = 1; i <= n; i ++){
cin >> a[i];
mp[a[i]] ++;
}
sort(a + 1, a + n + 1);
int ans = 0;
for(auto [x, y] : mp){
if(y >= 2){
int l = 0, r = n;
while(l < r){
int mid = l + r + 1 >> 1;
if(a[mid] >= x) r = mid - 1;
else l = mid;
}
ans += y * (y - 1) / 2 * l;
}
if(y >= 3){
ans += y * (y - 1) * (y - 2) / 6;
}
}
cout << ans << '\n';
}
C. Closest Cities
题意:一条数线上有 n 个城市,每个城市到离自己最近的城市仅消耗一枚金币,每次查询从 x 到 y 有两种选择:
1:前往任意其他城市 y,支付 |ax-ay| 枚金币
2:前往离 x 最近的城市,支付 1 枚金币
求 x 到 y 消耗的最少金币数量
解题思路:考虑用前缀和的方式求解,预处理每个城市到它后一个城市的最短距离和每一个城市到它前一个城市的最短距离,然后求前缀和
最直接的方式直达:res1 = abs(a[x] - a[y]);
1:当 x < y 也就是从 x 到它后面的城市,res2 = c[x] - c[y]
2:当 x > y 也就是从 x 到它签名档城市,res2 = b[x] - b[y]
然后答案就是 min(res1, res2)
查看代码 int n, m, a[N], b[N], c[N];
void solve(){
cin >> n;
for(int i = 1; i <= n; i ++) cin >> a[i];
for(int i = 2; i <= n; i ++){
if(a[i] - a[i - 1] < a[i + 1] - a[i]) b[i] = 1;
else b[i] = a[i] - a[i - 1];
}
for(int i = n - 1; i >= 1; i --){
if(a[i + 1] - a[i] < a[i] - a[i - 1]) c[i] = 1;
else c[i] = a[i + 1] - a[i];
}
c[1] = 1, b[n] = 1;
for(int i = 1; i <= n; i ++) b[i] += b[i - 1];
for(int i = n - 1; i >= 1; i --) c[i] += c[i + 1];
cin >> m;
while(m --){
int x, y;
cin >> x >> y;
int res1 = abs(a[x] - a[y]), res2;
if(x < y){
res2 = c[x] - c[y];
}
else res2 = b[x] - b[y];
cout << min(res1, res2) << '\n';
}
}
D. Berserk Monsters
题意:有 n 只怪物,每只怪物有两个参数:攻击力 a[i],防御力 d[i],进行 n 回合游戏,每个回合怪物会攻击与它相邻的怪兽,如果一只怪物在一个回合承受的伤害超过了它的防御值,那么它就会死亡,求每个回合死亡的怪物的数量
解题思路:算是模拟?链表模拟,用 set 存储,先找出第一回合会被杀死的怪物,然后把这只怪物删除,如果它的左边怪物或者右边怪物在下一回合会被杀死,那么就加入set
查看代码 void solve(){
int n;
cin >> n;
vector<int> a(n), d(n), l(n, -1), r(n, -1), ans(n);
vector<bool> vis(n);
for(auto &ai : a) cin >> ai;
for(auto &di : d) cin >> di;
for(int i = 0; i < n; i ++){
if(i != 0) l[i] = i - 1;
if(i != n - 1) r[i] = i + 1;
}
auto check = [&](int x){
int sum = 0;
if(l[x] != -1) sum += a[l[x]];
if(r[x] != -1) sum += a[r[x]];
return !vis[x] && sum > d[x];
};//判断能不能删去这个点
auto del = [&](int x){
vis[x] = true;
if(l[x] != -1) r[l[x]] = r[x];//左边节点的右节点变成当前节点的右节点
if(r[x] != -1) l[r[x]] = l[x];//有边界的的左节点变成当前节点的左节点
};//删点
set<int> s1;
for(int i = 0; i < n; i ++){
if(check(i)) s1.insert(i);
}
for(int i = 0; i < n; i ++){
ans[i] = s1.size();
set<int> s2;
for(auto v : s1) del(v);//删去每个该删去的点
for(auto v : s1){
if(l[v] != -1 && check(l[v])) s2.insert(l[v]);//如果当前点存在左节点,并且左节点的下一轮会被删掉
if(r[v] != -1 && check(r[v])) s2.insert(r[v]);//同理
}
s1 = s2;
}
for(auto i : ans) cout << i << ' ';
cout << '\n';
}
E. Increasing Subsequences
题意:构造出一个长度不超过200的有 x 个严格上升子序列的数组,空序列和单个数字的序列也算严格上升子序列
解题思路:长度为 n 的严格递增序列有 2n个严格单调递增子序列,先构造出最接近 x 的严格递增序列,然后发现在这个序列后面按照倒序的加上对应的某一项的数字,可以增加2(i - 1)个单调递增子序列,直接构造即可
查看代码 void solve(){
int x;
cin >> x;
vector<int> v;
int ans = 1, u = 1;
while(ans * 2 <= x){
v.push_back(u);
u ++;
ans *= 2;
}
ans = x - ans;
vector<int> b;
while(ans){
b.push_back(ans % 2);
ans /= 2;
}
reverse(b.begin(), b.end());
int p = v.size() - (v.size() - b.size());
for(int i = 0; i < b.size(); i ++){
if(b[i] == 1) v.push_back(p);
p --;
}
cout << v.size() << '\n';
for(auto vi : v){
cout << vi << ' ';
}
cout << '\n';
}
标签:s2,Educational,Rated,int,auto,s1,Codeforces,cin,ans
From: https://www.cnblogs.com/RosmontisL/p/17975080