Codeforces Round 895 (Div. 3)
A. Two Vessels
算出一个容器需要改变多少水量,除以c向上取整即可
void solve(){
double a, b, c;
cin >> a >> b >> c;
double d = fabs(a - b) / 2.0;
cout << (int)ceil(d / c) << '\n';
}
B. The Corridor or There and Back Again)
对于一个陷阱,最多能往它后面走 (s[i] - 1)/2 格子
算出每个陷阱的限制,去min即可
void solve(){
cin >> n;
for(int i = 1;i <= n;i++ ) cin >> d[i] >> s[i];
int mn = INT_MAX;
for(int i = 1;i <= n;i++ ){
len[i] = d[i] + (s[i] - 1) / 2;
mn = min(mn, len[i]);
}
cout << mn << '\n';
}
C. Non-coprime Split
从 l l l 开始枚举 a+b 的值,若当前值不是素数,则令a为它的最小非1因子,b即可相减得出
void solve(){
int l, r;
cin >> l >> r;
for(int i = l;i <= r;i++){
for(int j = 2, len = sqrt(i);j <= len;j++){
if(i % j == 0){
cout << j << ' ' << i - j << '\n';
return;
}
}
}
cout << "-1\n";
}
D. Plus Minus Permutation
求出需要加的数的个数、需要减的个数、加与减重叠的个数,将加的个数和减的个数分别减去重叠的个数得到独立加的个数和独立减的个数,最后答案就是独立加的位置放最大的数,独立减的位置放最小的数,等差数列求和即可
void solve(){
int x, y;
cin >> n >> x >> y;
int z = (x * y) / __gcd(x, y);
int ad = n / x;
int dv = n / y;
int sm = n / z;
ad -= sm;
dv -= sm;
int ans = 0;
ans -= (dv * (1 + dv)) / 2;
ans += (ad * (2 * n - ad + 1)) / 2;
cout << ans << '\n';
}
E. Data Structures Fan
分别记录0位置和1位置的数的前缀异或和 p r e [ 0 ] [ i ] , p r e [ 1 ] [ i ] pre[0][i], pre[1][i] pre[0][i],pre[1][i]、所有0位置数的异或和和所有1位置数的异或和 a n s [ 0 ] , a n s [ 1 ] ans[0], ans[1] ans[0],ans[1]
区间反转时将 a n s [ 0 ] , a n s [ 1 ] ans[0],ans[1] ans[0],ans[1]都与反转区间的0、1对应数的异或和异或起来即可
查询操作直接输出对应异或和
void init(){
ans[0] = ans[1] = 0;
for(int i = 0;i <= n;i++) pre[0][i] = pre[1][i] = 0;
}
void solve(){
cin >> n;
init();
for(int i = 1;i <= n;i++) cin >> a[i];
string s;
cin >> s;
s = ' ' + s;
for(int i = 1;i <= n;i++){
pre[0][i] ^= pre[0][i-1];
pre[1][i] ^= pre[1][i-1];
pre[s[i] - '0'][i] ^= a[i];
}
ans[0] = pre[0][n];
ans[1] = pre[1][n];
cin >> q;
while(q--){
int op, l, r;
cin >> op >> l;
if(op == 1){
cin >> r;
ans[0] ^= pre[0][r] ^ pre[0][l-1] ^ pre[1][r] ^ pre[1][l-1];
ans[1] ^= pre[0][r] ^ pre[0][l-1] ^ pre[1][r] ^ pre[1][l-1];
}else{
cout << ans[l] << ' ';
}
}
cout << '\n';
}
F. Selling a Menagerie
题目给出的图一定有环,环外可能连有链,先把这些链的动物卖掉,图就只剩下环,对于一个环,其中收益最小的动物最后卖,所以从该动物的下一个开始卖直到将环删完即可
利用度模拟删点实现较为简单
int n, m, a[N], c[N], vis[N], d[N];
void init(){
for(int i = 0;i <= n;i++){
d[i] = vis[i] = 0;
}
}
void solve(){
cin >> n;
init();
for(int i = 1;i <= n;i++) {
cin >> a[i];
d[a[i]]++;
}
for(int i = 1;i <= n;i++) cin >> c[i];
for(int i = 1;i <= n;i++) if(d[i] == 0 && !vis[i]){
int cur = i;
while(d[cur] == 0){
cout << cur << ' ';
vis[cur] = 1;
d[a[cur]]--;
cur = a[cur];
}
}
for(int i = 1;i <= n;i++) if(!vis[i]){
int mn = i, cur = a[i];
while(cur != i){
if(c[cur] < c[mn]) mn = cur;
cur = a[cur];
}
cur = a[mn];
while(1){
cout << cur << ' ';
vis[cur] = 1;
if(cur == mn) break;
cur = a[cur];
}
}
cout << '\n';
}
G. Replace With Product
考虑极端情况,如果数组中只有两个大于1的数,2和1e9,那就直接选择2和1e9的下标。
所以如果所有数乘积大于1e9就直接选择最左边和最右边的大于1的数,
否则的话说明大于1的数不超过 log(1e9)个,直接在这几个数中暴力枚举l,r区间即可
void solve(){
cin >> n;
for(int i = 1;i <= n;i++) {
cin >> a[i];
}
int l = 1, r = n;
while(l < n && a[l] == 1) l++;
while(r > 1 && a[r] == 1) r--;
int prod = 1;
for(int i = l;i <= r;i++){
prod *= a[i];
if(prod > 1e9){
cout << l << ' ' << r << '\n';
return;
}
}
for(int i = 1;i <= n;i++){
pre[i] = pre[i-1] + a[i];
pro[i] = pro[i-1] * a[i];
}
vector<int>num;
for(int i = l;i <= r;i++)
if(a[i] > 1) num.push_back(i);
int L = 1, R = 1, ans = 0;
for(int i = 0;i < num.size();i++){
for(int j = i;j < num.size();j++){
int d = (pro[num[j]] / pro[num[i]-1]) - (pre[num[j]] - pre[num[i]-1]);
if(d > ans){
ans = d;
L = num[i];
R = num[j];
}
}
}
cout << L << ' ' << R << '\n';
}