B - Which is ahead?
难度: ⭐
题目大意
给定n个人的位置顺序, 现有m次询问, 给出a, b两个人, 问谁在前面;
解题思路
模拟就行;
神秘代码
#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define endl '\n'
using namespace std;
const int N = 2e5 + 10, mod = 998244353, inf = 1e18;
typedef pair<int, int> PII;
int n, m, k;
int p[N];
signed main(){
cin >> n;
for(int i = 1; i <= n; i++){
int x;
cin >> x;
p[x] = i;
}
cin >> m;
for(int i = 1; i <= m; i++){
int a, b;
cin >> a >> b;
if(p[a] < p[b]) cout << a << endl;
else cout << b << endl;
}
return 0;
}
C - Many Replacement
难度: ⭐⭐⭐
题目大意
现有字符串s, 现有m次操作, 每次操作给出两个字符a, b; 要求把字符串s中所有的a都换成b; 最后输出字符s
解题思路
本题可以用哈希来做, 开一个长度为26的数组p[26]用来表示此时的字母x表示的是哪个字母, 初始当然都是自己; 每次修改时, 先遍历26个字母, 看都有谁的p[i] = a, 然后把它们都改成b即可; 最后输出s的时候输出每个字母所对应的p即可;
神秘代码
#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define endl '\n'
using namespace std;
const int N = 2e5 + 10, mod = 998244353, inf = 1e18;
typedef pair<int, int> PII;
int n, m, k;
string s;
int p[N];
signed main(){
cin >> n >> s >> m;
for(int i = 0; i < 26; i++) p[i] = i;
while(m--){
char a, b;
cin >> a >> b;
for(int i = 0; i < 26; i++){
if(p[i] == a - 'a') p[i] = b - 'a';
}
}
for(int i = 0; i < n; i++){
printf("%c", p[s[i] - 'a'] + 'a');
}
return 0;
}
D - Square Pair
难度: ⭐⭐⭐
题目大意
给定n个数字Ai, 问有多少个满足条件的二元组(i, j), 条件如下
一是Ai * Aj是一个平方数;
二是i < j;
解题思路
暴力做法是O(n2)显然会超时, 所以要从平方数下手; 已知定理, 任何一个数都可以化为多个质数的乘积; 如果a * b是一个平方数并且a != b的话, 我们把组成a和b的质数都列出来, 并且让两者同一质数的数量相加, 那么我们会发现所有质数的数量都是偶数, 因为这样才会相乘是一个平方数; 由这一发现还不足以解题, 所以我们可以先把a和b进行化简, 拿a来说, 把组成a的质数列出来之后可以把其中数量大于等于2的质数数量减到0或1, 用代码实现就是遍历小于a的平方数, 让a减去其中可以被a整除的; 化简完后我们发现a = b, 这样我们就可以解题了; 把所有数化简后遍历数组, 对于数字a, 结果res就加上cnt(a) - 1; cnt(a)指数组中a的数量; 又因为二元组要求i < j; 所以最后res要除以二;
本题还有个特殊情况就是0, 0可以和任何数搭配, 所以只需要关心i < j即可; 对于下标i, 我们用cnt[i]记录前i个数字中有几个0; 对于每个0, 我们将其看作二元组的前一个; 所以结果加上n - cnt[i]即可;
神秘代码
#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define endl '\n'
using namespace std;
const int N = 2e5 + 10, mod = 998244353, inf = 1e18;
typedef pair<int, int> PII;
int n, m, res;
string s;
int p[N], cnt[N];
map<int, int> mp;
signed main(){
cin >> n;
for(int i = 1; i <= n; i++){
cin >> p[i];
for(int j = 2; j * j <= p[i]; j++){
while(p[i] % (j * j) == 0){
p[i] /= (j * j);
}
}
mp[p[i]]++;
cnt[i] = cnt[i - 1] + (p[i] == 0);
}
int a = 0, b = 0, c = n - 1;
for(int i = 1; i <= n; i++){
if(p[i] == 0) {
a += n - cnt[i];
}
else b += (mp[p[i]] - 1);
}
cout << a + b / 2;
return 0;
}
E - Last Train
难度: ⭐⭐⭐⭐
题目大意
现有n个车站, 每个车站都有6个属性, l, d, k, c, A, B; 从时刻l开始发车, 每隔时间d发一辆, 一共发k辆; 并且火车是从A点前往B点, 所需时间是c; 设F(x)指从车站x的车最晚什么时候出发可以到车站n;
解题思路
因为所有车站的目标都是n, 那么我们可以从车站n开始反向进行最短路dijkstra; 找到从v出发可以到达u的最晚的一班车; 如果v的l + c > F(u); 则说明从v来的车赶不上u的满足条件的最晚的那班车; 否则我们找的车次就是num = min((F(u) - (l + c)) / d, k - 1); 然后就可以用l + num * d来更新F(u);
神秘代码
#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define endl '\n'
using namespace std;
const int N = 2e5 + 10, mod = 998244353, inf = 2e18;
typedef pair<int, int> PII;
int n, m, res;
string s;
struct node{
int u, l, d, k, c;
};
node P[N];
vector<node> v[N];
int dis[N];
void dijkstra(){
for(int i = 1; i <= n; i++) dis[i] = -inf;
priority_queue<PII> heap;
heap.push({inf, n});
dis[n] = inf;
while(heap.size()){
PII t = heap.top();
heap.pop();
int id = t.second;
for(auto x : v[id]){
int y = dis[id] - (x.l + x.c);
if(y < 0) continue;
int num = x.l + min(y / x.d, x.k - 1) * x.d;
if(num > dis[x.u]){
dis[x.u] = num;
heap.push({dis[x.u], x.u});
}
}
}
}
signed main(){
cin >> n >> m;
for(int i = 1; i <= m; i++){
int l, d, k, c, a, b;
cin >> l >> d >> k >> c >> a >> b;
v[b].push_back({a, l, d, k, c});
}
dijkstra();
for(int i = 1; i < n; i++){
if(dis[i] == -inf) cout << "Unreachable" << endl;
else cout << dis[i] << endl;
}
return 0;
}