G题只会暴力..不会数据结构
A - 问题 Generator
暴力模拟即可
// Problem: A. Problem Generator
// Contest: Codeforces - Codeforces Round 950 (Div. 3)
// URL: https://codeforces.com/contest/1980/problem/A
// Memory Limit: 256 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define x first
#define y second
#define endl '\n'
const LL maxn = 4e05+7;
const LL N = 5e05+10;
const LL mod = 1e09+7;
const int inf = 0x3f3f3f3f;
const LL llinf = 5e18;
typedef pair<int,int>pl;
priority_queue<LL , vector<LL>, greater<LL> >mi;//小根堆
priority_queue<LL> ma;//大根堆
LL gcd(LL a, LL b){return b > 0 ? gcd(b , a % b) : a;
}LL lcm(LL a , LL b){return a / gcd(a , b) * b;
}
int n , m;
vector<int>a(N , 0);
void init(int n){for(int i = 0 ; i <= n ; i ++){a[i] = 0;}
}
void solve()
{int a[7];int n , m;cin >> n >> m;for(int i = 0 ; i < 7 ; i ++){a[i] = m;} string s;cin >> s;for(auto c : s){a[c - 'A']--;}int cnt = 0 ;for(int i = 0 ; i < 7 ;i ++){cnt += max(0 , (a[i]));}cout << cnt << endl;
}
int main()
{ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cout.precision(10);int t=1;cin>>t;while(t--){solve();}return 0;
}
B - Choosing Cubes
题意:
还是暴力模拟,记录一下最喜欢立方体在排序后的左右界,然后搞一搞
// Problem: B. Choosing Cubes
// Contest: Codeforces - Codeforces Round 950 (Div. 3)
// URL: https://codeforces.com/contest/1980/problem/B
// Memory Limit: 256 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define x first
#define y second
#define endl '\n'
const LL maxn = 4e05+7;
const LL N = 5e05+10;
const LL mod = 1e09+7;
const int inf = 0x3f3f3f3f;
const LL llinf = 5e18;
typedef pair<int,int>pl;
priority_queue<LL , vector<LL>, greater<LL> >mi;//小根堆
priority_queue<LL> ma;//大根堆
LL gcd(LL a, LL b){return b > 0 ? gcd(b , a % b) : a;
}LL lcm(LL a , LL b){return a / gcd(a , b) * b;
}
int n , m;
vector<int>a(N , 0);
void init(int n){for(int i = 0 ; i <= n ; i ++){a[i] = 0;}
}
bool cmp(int a , int b){return a > b;
}
void solve()
{int n , f , k;cin >> n >> f >> k;for(int i = 1 ; i <= n ; i ++)cin >> a[i];int tar = a[f];sort(a.begin() + 1 , a.begin() + 1 + n , cmp);int l = -1 , r;for(int i = 1 ; i <= n ; i ++){if(a[i] == tar){if(l == -1){l = i;}r = i;}}if(l > k){cout <<"No\n";}else if(r <= k){cout <<"Yes\n";}else{cout <<"Maybe\n";}
}
int main()
{ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cout.precision(10);int t=1;cin>>t;while(t--){solve();}return 0;
}
C - Sofia and the Lost Operations
题意:
思路:若最后一个修改数存在于b数组中,那么只需要看这些修改的数能否把a数组中待修改的数全部覆盖即可,否则一定不存在。
// Problem: C. Sofia and the Lost Operations
// Contest: Codeforces - Codeforces Round 950 (Div. 3)
// URL: https://codeforces.com/contest/1980/problem/C
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define x first
#define y second
#define int long long
#define endl '\n'
const LL maxn = 4e05+7;
const LL N = 5e05+10;
const LL mod = 1e09+7;
const int inf = 0x3f3f3f3f;
const LL llinf = 5e18;
typedef pair<int,int>pl;
priority_queue<LL , vector<LL>, greater<LL> >mi;//小根堆
priority_queue<LL> ma;//大根堆
LL gcd(LL a, LL b){return b > 0 ? gcd(b , a % b) : a;
}LL lcm(LL a , LL b){return a / gcd(a , b) * b;
}
int n , m;
vector<int>a(N , 0);
void init(int n){for(int i = 0 ; i <= n ; i ++){a[i] = 0;}
}
void solve()
{int n;cin >> n;int a[n] , b[n];for(int i = 0 ; i < n ; i ++)cin >> a[i];for(int i = 0 ; i < n ; i ++)cin >> b[i];set<int>st;map<int , int>mp;for(int i = 0 ; i < n ; i ++)st.insert(b[i]);for(int i = 0 ; i < n ; i ++){if(a[i] != b[i]){mp[b[i]]++;}}int m;cin >> m;vector<int>tmp;for(int i = 0 ; i < m ; i ++){int x;cin >> x;tmp.pb(x);}if(st.count(tmp[tmp.size() - 1])){for(auto it : tmp){mp[it]--;}int ok = 1;for(auto it : mp){if(it.second > 0){ok = 0;}}if(ok)cout <<"YES\n";elsecout <<"NO\n";}else{cout <<"NO\n";}
}
signed main()
{ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cout.precision(10);int t=1;cin>>t;while(t--){solve();}return 0;
}
D - GCD-sequence
题意:
思路:将删除前的gcd序列求出来,可以发现若要满足题意,必然需要找到gcd序列中最后一个递减的位置,并且删除与之相关的数(只有三个数与之相关)。然后判断删除后的序列能否形成非递减即可。
// Problem: D. GCD-sequence
// Contest: Codeforces - Codeforces Round 950 (Div. 3)
// URL: https://codeforces.com/contest/1980/problem/D
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define x first
#define y second
#define endl '\n'
const LL maxn = 4e05+7;
const LL N = 5e05+10;
const LL mod = 1e09+7;
const int inf = 0x3f3f3f3f;
const LL llinf = 5e18;
typedef pair<int,int>pl;
priority_queue<LL , vector<LL>, greater<LL> >mi;//小根堆
priority_queue<LL> ma;//大根堆
LL gcd(LL a, LL b){return b > 0 ? gcd(b , a % b) : a;
}LL lcm(LL a , LL b){return a / gcd(a , b) * b;
}
int n , m;
vector<int>a(N , 0);
void init(int n){for(int i = 0 ; i <= n ; i ++){a[i] = 0;}
}
void solve()
{int n;cin >> n;for(int i = 0 ; i < n ; i ++){cin >> a[i];} vector<int>b;for(int i = 1 ; i < n ; i ++){b.pb(__gcd(a[i] , a[i - 1]));}int f1 = -1, f2 = -1 , f3 = -1;for(int i = b.size() - 1 ; i >= 1 ; i --){if(b[i - 1] > b[i]){f1 = i + 1;f2 = i;f3 = i - 1;break;}}if(f1 == -1){cout << "YES\n";return;}else{vector<int>tmp;vector<int>tmpb;for(int i = 0 ; i < n ; i ++){if(i == f1) continue;tmp.pb(a[i]);}for(int i = 1 ; i < n - 1; i ++){tmpb.pb(__gcd(tmp[i] , tmp[i - 1]));} int ok = 1;for(int i = 1 ; i < n - 2 ; i ++){if(tmpb[i] >= tmpb[i - 1]) continue;else ok = 0;}if(ok){cout <<"YES\n";return;}tmp.clear();tmpb.clear();for(int i = 0 ; i < n ; i ++){if(i == f2) continue;tmp.pb(a[i]);}for(int i = 1 ; i < n - 1; i ++){tmpb.pb(__gcd(tmp[i] , tmp[i - 1]));} ok = 1;for(int i = 1 ; i < n - 2 ; i ++){if(tmpb[i] >= tmpb[i - 1]) continue;else ok = 0;}if(ok){cout <<"YES\n";return;}tmp.clear();tmpb.clear();for(int i = 0 ; i < n ; i ++){if(i == f3) continue;tmp.pb(a[i]);}for(int i = 1 ; i < n - 1; i ++){tmpb.pb(__gcd(tmp[i] , tmp[i - 1]));} ok = 1;for(int i = 1 ; i < n - 2 ; i ++){if(tmpb[i] >= tmpb[i - 1]) continue;else ok = 0;}if(ok){cout <<"YES\n";return;}}cout <<"NO\n";
}
int main()
{ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cout.precision(10);int t=1;cin>>t;while(t--){solve();}return 0;
}
E - Permutation of Rows and Columns
题意:给定两个矩阵,每个格子中有一个唯一的数。求这两个矩阵能否通过行变换,列变换变成相同的矩阵。
思路:可以发现无论怎么变换,一行/一列中的数的情况是一样的,因此只需要看两个矩阵每一行/每一列中的数是否匹配即可。
// Problem: E. Permutation of Rows and Columns
// Contest: Codeforces - Codeforces Round 950 (Div. 3)
// URL: https://codeforces.com/contest/1980/problem/E
// Memory Limit: 256 MB
// Time Limit: 3000 ms
//
// Powered by CP Editor (https://cpeditor.org)#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define x first
#define y second
#define endl '\n'
const LL maxn = 4e05+7;
const LL N = 5e05+10;
const LL mod = 1e09+7;
const int inf = 0x3f3f3f3f;
const LL llinf = 5e18;
typedef pair<int,int>pl;
priority_queue<LL , vector<LL>, greater<LL> >mi;//小根堆
priority_queue<LL> ma;//大根堆
LL gcd(LL a, LL b){return b > 0 ? gcd(b , a % b) : a;
}LL lcm(LL a , LL b){return a / gcd(a , b) * b;
}
int n , m;
vector<int>a(N , 0);
void init(int n){for(int i = 0 ; i <= n ; i ++){a[i] = 0;}
}
void solve()
{int n , m;cin >> n >> m;int a[n][m];for(int i = 0 ; i < n ; i ++){for(int j = 0 ; j < m ; j ++)cin >> a[i][j];} int b[n][m];for(int i = 0 ; i < n ; i ++){for(int j = 0 ; j < m ; j ++)cin >> b[i][j];} map< set<int> , int> mp;map< set<int> , int> pm; for(int i = 0 ; i < n ; i ++){set<int>tmp;for(int j = 0 ; j < m ; j ++){tmp.insert(a[i][j]);}mp[tmp]++;}for(int i = 0 ; i < m ; i ++){set<int>tmp;for(int j = 0 ; j < n ; j ++){tmp.insert(a[j][i]);}pm[tmp]++;} for(int i = 0 ; i < n ; i ++){set<int>tmp;for(int j = 0 ; j < m ; j ++){tmp.insert(b[i][j]);}if(mp.count(tmp)){continue;}else{cout <<"NO\n";return;}}for(int i = 0 ; i < m ; i ++){set<int>tmp;for(int j = 0 ; j < n ; j ++){tmp.insert(b[j][i]);}if(pm.count(tmp)){continue;}else{cout <<"NO\n";return;}} cout <<"YES\n";
}
int main()
{ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cout.precision(10);int t=1;cin>>t;while(t--){solve();}return 0;
}
F2 - Field Division (hard version)
思路:(纯暴力做法)可以发现:若一个喷泉的左下方存在另一个喷泉,那么Alice就不会划线到该喷泉旁边,而是会划到左下方喷泉中最左边的那个喷泉的左侧。 因此只需要记录一下每一行左下方最左侧喷泉的位置即可,然后再计算每一行划了多少,由于矩阵很大,所以需要离散化处理。
另外如何判断删除某喷泉后会增加多少,同样是模拟删除该喷泉后的,在其上方的喷泉的情况,然后如果跟没删除前一样就不用再模拟下去了。
// Problem: F1. Field Division (easy version)
// Contest: Codeforces - Codeforces Round 950 (Div. 3)
// URL: https://codeforces.com/contest/1980/problem/F1
// Memory Limit: 256 MB
// Time Limit: 3000 ms
//
// Powered by CP Editor (https://cpeditor.org)#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define x first
#define y second
#define endl '\n'
const LL maxn = 4e05+7;
const LL N = 5e05+10;
const LL mod = 1e09+7;
const int inf = 0x3f3f3f3f;
const LL llinf = 5e18;
#define int long long
typedef pair<int,int>pl;
priority_queue<LL , vector<LL>, greater<LL> >mi;//小根堆
priority_queue<LL> ma;//大根堆
LL gcd(LL a, LL b){return b > 0 ? gcd(b , a % b) : a;
}LL lcm(LL a , LL b){return a / gcd(a , b) * b;
}
int n , m;
vector<int>a(N , 0);
void init(int n){for(int i = 0 ; i <= n ; i ++){a[i] = 0;}
}
void solve()
{int n , m , k;cin >> n >> m >> k;pair<int,int>p[k];for(int i = 0 ; i < k ; i ++){cin >> p[i].x >> p[i].y;} set<int>st;for(int i = 0 ; i < k ; i ++){st.insert(p[i].x);}int idx = 0;map<int,int>mp;map<int,int>pm;for(auto it : st){mp[it] = ++idx;pm[idx] = it;}map<int , set<int> >left;for(int i = 0 ; i < k ; i ++){int idx = mp[p[i].x];left[idx].insert(p[i].y);}vector<int>pre(idx + 5 , m + 1);for(int i = idx; i >= 0 ; i --){if(i != 0)pre[i] = min(pre[i + 1] , *left[i].begin());elsepre[i] = pre[i + 1];}int ans = 0;for(int i = 0 ; i <= idx ; i ++){int l , r;if(i == 0){l = 0;}else{l = pm[i];}if(i == idx){r = n;}else{r = pm[i + 1];}ans += (pre[i + 1] - 1) * (r - l);}cout << ans << endl;for(int i = 0 ; i < k ; i ++){int idx = mp[p[i].x];if(p[i].y > *left[idx].begin()){cout << 0 << " ";}else{if(p[i].y < pre[idx + 1]){auto it = left[idx].begin();it++;int x;if(it == left[idx].end())x = pre[idx + 1];elsex = *it;int out = 0;x = min(x , pre[idx + 1]);out += (x - p[i].y) * (pm[idx] - pm[idx - 1]);for(int i = idx - 1; i >= 0 ; i --){x = min(x , *left[i].begin());if(x == pre[i]) break;out += (x - pre[i]) * (pm[i] - pm[i - 1]); }cout << out << " ";}else{cout << 0 << " ";}}}cout << endl;
}
signed main()
{ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cout.precision(10);int t=1;cin>>t;while(t--){solve();}return 0;
}