题意:给定一个数 , 两个人玩游戏,每人能够执行 操作,若操作完是3的倍数则获胜,问先手的人能否获胜(若无限循环则先手的人输)。
思路:假如一个数模3余1或者2,那么第一轮操作先手就能获胜,若余0则后手获胜。
- // Problem: A. Game with Integers
- // Contest: Codeforces - Codeforces Round 909 (Div. 3)
- // URL: https://codeforces.com/contest/1899/problem/A
- // Memory Limit: 256 MB
- // Time Limit: 1000 ms
- //
- // Powered by CP Editor (https://cpeditor.org)
-
- #include
- 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=1e05+10;
- const LL mod=1e09+7;
- typedef pair<int,int>pl;
- priority_queue
, greater >t; - priority_queue
q; - 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;
- int a[N];
- void init(int n){
- for(int i = 0 ; i <= n ; i ++){
- a[i] = 0;
- }
- }
- void solve()
- {
- cin >> n;
- if(n % 3 == 0){
- cout << "Second\n";
- }
- else{
- cout << "First\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;
- }
题意:给定一个整数 , 表示有 个集装箱,接下来给定一个数组 , 代表了第个集装箱有吨重。现要将个集装箱恰好分成连续的组。要求这当中所有的取值下集装箱重量的最大值减去最小值的最大值。
思路:直接暴力做 , 假设每一组有1、2、3、4、...n个,看满足题意的情况下最大值减最小值的值。时间复杂度O(NlogN).
- // Problem: B. 250 Thousand Tons of TNT
- // Contest: Codeforces - Codeforces Round 909 (Div. 3)
- // URL: https://codeforces.com/contest/1899/problem/B
- // Memory Limit: 256 MB
- // Time Limit: 2000 ms
- //
- // Powered by CP Editor (https://cpeditor.org)
-
- #include
- 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=2e05+10;
- const LL mod=1e09+7;
- typedef pair<int,int>pl;
- priority_queue
, greater >t; - priority_queue
q; - 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;
- LL a[N] , sum[N];
- void init(int n){
- for(int i = 0 ; i <= n ; i ++){
- a[i] = 0;
- }
- }
- void solve()
- {
- cin >> n;
- for(int i = 1 ; i <= n ; i ++){
- cin >> a[i];
- sum[i] = sum[i - 1] + a[i];
- }
- LL ans = 0;
- for(int i = 1 ; i <= n ; i ++){
- LL maxx = 0 , minn = 1e18;
- if(n % i == 0){
- for(int j = 0 ; j < n ; j += i){
- maxx = max(sum[j + i] - sum[j] , maxx);
- minn = min(minn , sum[j + i] - sum[j]);
- }
- ans = max(ans , maxx - minn);
- }
- }
- cout << ans<
- }
- 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;
- }
1899C - Yarik and Array
题意:给定一组序列,求连续奇数偶数非空子序列的和的最大值(相邻的奇偶性不能相同)。
思路:同最大连续子序列差不多的做法,只不过要求前一项和当前的奇偶性不同,且至少要选一项。时间O(N)。
- // Problem: C. Yarik and Array
- // Contest: Codeforces - Codeforces Round 909 (Div. 3)
- // URL: https://codeforces.com/contest/1899/problem/C
- // Memory Limit: 256 MB
- // Time Limit: 1000 ms
- //
- // Powered by CP Editor (https://cpeditor.org)
-
- #include
- 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=2e05+10;
- const LL mod=1e09+7;
- typedef pair<int,int>pl;
- priority_queue
, greater >t; - priority_queue
q; - 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;
- LL a[N];
- int dp[N][2];
- void init(int n){
- for(int i = 0 ; i <= n ; i ++){
- a[i] = 0;
- }
- }
- void solve()
- {
- int n;
- cin >> n;
- for(int i = 1 ; i <= n ; i ++)
- cin >> a[i];
- LL ans = -1e18;
- LL now = 0;
- for(int i = 1 ; i <= n ; i ++){
- if(now == 0){
- now += a[i];
- }
- else{
- if(abs(a[i]) % 2 == abs(a[i - 1]) % 2 ){
- now = a[i];
- }
- else{
- if(now > 0)
- now += a[i];
- else
- now = a[i];
- }
- }
- ans = max(ans , now);
- // cout << now << endl;
- if(now < 0)
- now = 0;
- }
- cout << ans << 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;
- }
1899D - Yarik and Musical Notes
题意:给定一组数,要求数对满足的数量。
思路:构造辅助哈希(范围过大无法构造数组) , 标记了当前位置之后有多少个数字。观察后发现 , 当 时能够满足,其余均需要i = j " role="presentation" style="position: relative;">才能满足。因此对于1或者2而言,数对的数量为 ,其余的 i 构成的数对数量都是。首先遍历一遍算出,然后再遍历一遍求答案,同时不断更新即可。
- // Problem: D. Yarik and Musical Notes
- // Contest: Codeforces - Codeforces Round 909 (Div. 3)
- // URL: https://codeforces.com/contest/1899/problem/D
- // Memory Limit: 256 MB
- // Time Limit: 1000 ms
- //
- // Powered by CP Editor (https://cpeditor.org)
-
- #include
- 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=3e05+10;
- const LL mod=1e09+7;
- typedef pair<int,int>pl;
- priority_queue
, greater >t; - priority_queue
q; - 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;
- int a[N];
- void init(int n){
- for(int i = 0 ; i <= n ; i ++){
- a[i] = 0;
- }
- }
- void solve()
- {
- cin >> n;
- unordered_map
mp; - LL ans = 0;
- for(int i = 1 ; i <= n ; i ++){
- cin >> a[i];
- mp[a[i]]++;
- }
- for(int i = 1 ; i <= n ; i ++){
- mp[a[i]]--;
- if(a[i] == 1 || a[i] == 2){
- ans += mp[1] + mp[2];
- }
- else{
- ans += mp[a[i]];
- }
- }
- cout << ans << 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;
- }
1899E - Queue Sort
题意:给定一个数组,每次能够进行如下操作:
1、选择第一个数放入数组最后一个。
2、将最后一个数往前交换,直到到达第一位或者比前一个数大为止。
问将数组变为递增的最少操作数,若无法则输出-1.
思路:若最小的数为数组第一个,那么一轮操作之后他还是在第一位,这样便会无限循环。因此只需要满足最小的数之后的数全是递增的即可。
- // Problem: E. Queue Sort
- // Contest: Codeforces - Codeforces Round 909 (Div. 3)
- // URL: https://codeforces.com/contest/1899/problem/E
- // Memory Limit: 256 MB
- // Time Limit: 1000 ms
- //
- // Powered by CP Editor (https://cpeditor.org)
-
- #include
- 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=3e05+10;
- const LL mod=1e09+7;
- typedef pair<int,int>pl;
- priority_queue
, greater >t; - priority_queue
q; - 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;
- LL a[N];
- void init(int n){
- for(int i = 0 ; i <= n ; i ++){
- a[i] = 0;
- }
- }
- void solve()
- {
- cin >> n;
- LL minn = 1e18;
- for(int i = 1 ;i <= n ; i ++){
- cin >> a[i];
- minn = min(a[i] , minn);
- }
- /* for(int i = 1 ; i < n - 1; i++){
- if(a[i] < a[i + 1]){
- break;
- }
- if(i == n - 2){
- cout << 0 << endl;
- return;
- }
- }*/
- for(int i = 1 ; i <= n ; i ++){
- if(a[i] == minn){
- for(int j = i + 1; j <= n ; j ++){
- if(a[j] < a[j - 1]){
- cout << -1 << endl;
- return;
- }
- }
- cout << i - 1 << endl;
- return;
- }
- }
- }
- 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;
- }
1899F - Alex's whims
题意:现有n个顶点,起初你可以任意构造将其形成一棵树。接下来有 d 个数,表示共有d轮。每一轮你可以选择一个已有的边将其删除,然后再连一条边形成一颗新的数。要求每一轮能够满足至少有两个叶子结点的距离恰好为。
思路:首先可以将n个顶点连城一条链。然后每一轮当中,我们固定第一个点和最后一个点的距离为我们要的。每次我们可以将与点1相连的边删去,然后新增一条边,使得刚好1到n的距离为。由于结点2 ~ n都是一条链,所以2 ~ n - 1 任意一个距离都是可以构造出来的。如此便一定能够满足题意。所以我们只需要记录当前1结点和哪个结点相连,然后需要连到哪个结点即可。
- // Problem: F. Alex's whims
- // Contest: Codeforces - Codeforces Round 909 (Div. 3)
- // URL: https://codeforces.com/contest/1899/problem/F
- // Memory Limit: 256 MB
- // Time Limit: 1000 ms
- //
- // Powered by CP Editor (https://cpeditor.org)
-
- #include
- 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=1e05+10;
- const LL mod=1e09+7;
- typedef pair<int,int>pl;
- priority_queue
, greater >t; - priority_queue
q; - 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;
- int a[N];
- void init(int n){
- for(int i = 0 ; i <= n ; i ++){
- a[i] = 0;
- }
- }
- void solve()
- {
- cin >> n >> m;
- for(int i = 2 ; i <= n ; i ++){
- cout << i - 1 << " " << i << endl;
- }
- int pre = 2;
- for(int i = 0 ; i < m ; i ++){
- int x;
- cin >> x;
- int len = (n - pre) + 1;
- if(len == x){
- cout <<"-1 -1 -1\n";
- continue;
- }
- else{
- int to = (n - x + 1);
- cout << 1 << " " << pre << " " << to << endl;
- pre = to;
- }
- }
- }
- 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;
- }
1899G - Unusual 进入tainment
思路:给定一棵树和一个排列p。现有q组询问,每组询问包含了三个数。问点的子树的结点是否在中出现。
思路:子树问题,首先想到了用dfs序来解决。对于一颗子树而言,我们可以用set来维护其所有结点在排列p中的位置。然后对于一个询问而言,只需要找到set中大于等于 l 的第一个位置即可,然后判断该位置是否小于等于r。若小于等于r则代表了其子树的结点包含在了中。共有n个结点,所以我们需要创立n个set,来记录他们的结点在p中的位置。在子树向上合并的过程中,我们可以用启发式合并来实现优化:每一轮虽然是将子树的set合并到父节点的set上,但是可以用swap来交换两个set,确保每次都将小集合合并到大集合上面(swap是O(1)的)。如此总的时间复杂度是O(nlogn + qlogn)的。
- // Problem: G. Unusual Entertainment
- // Contest: Codeforces - Codeforces Round 909 (Div. 3)
- // URL: https://codeforces.com/contest/1899/problem/G
- // Memory Limit: 256 MB
- // Time Limit: 3000 ms
- //
- // Powered by CP Editor (https://cpeditor.org)
-
- #include
- 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=2e05+10;
- const LL mod=1e09+7;
- typedef pair<int,int>pl;
- priority_queue
, greater >t; - priority_queue
q; - 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;
- int a[N] , pos[N];
- vector<int>tr[N + 5];
- vector
int , 3 > >que[N]; - vector
int>> num(N); - void init(int n){
- for(int i = 0 ; i <= n ; i ++){
- a[i] = 0 , tr[i].clear() , que[i].clear();
- num[i].clear();
- }
- }
- LL ans[N];
- void merge(set<int> &a , set<int>&b){
- if(a.size() < b.size()){
- swap(a , b);
- }
- for(auto it : b){
- a.insert(it);
- }
- b.clear();
- }
- void dfs(int cur , int f){
- num[cur].insert(pos[cur]);
- for(auto it : tr[cur]){
- if(it == f)
- continue;
- dfs(it , cur);
- merge(num[cur] , num[it]);
- }
- for(auto it : que[cur]){
- auto p = num[cur].lower_bound(it[0]);
- ans[it[2]] = p != num[cur].end() && *p <= it[1];
- }
- };
- void solve()
- {
-
- cin >> n >> m;
- for(int i = 1 ; i < n ; i++){
- int x , y;
- cin >> x >> y;
- tr[x].pb(y);
- tr[y].pb(x);
- }
- for(int i = 1 ; i <= n ; i ++){
- cin >> a[i];
- pos[a[i]] = i;
- }
- for(int i = 0 ; i < m ; i ++){
- int l , r , x;
- cin >> l >> r >> x;
- que[x].pb({l , r , i});
- }
- dfs(1 , 0);
- for(int i = 0 ; i < m ; i ++){
- if(ans[i]){
- cout <<"YES\n";
- }
- else{
- cout <<"NO\n";
- }
- }
- init(n);
- cout << endl;
- num.clear();
- }
- 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;
- }
另外为何我这个会超时
- // Problem: G. Unusual Entertainment
- // Contest: Codeforces - Codeforces Round 909 (Div. 3)
- // URL: https://codeforces.com/contest/1899/problem/G
- // Memory Limit: 256 MB
- // Time Limit: 3000 ms
- //
- // Powered by CP Editor (https://cpeditor.org)
-
- #include
- 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=1e05+10;
- const LL mod=1e09+7;
- typedef pair<int,int>pl;
- priority_queue
, greater >t; - priority_queue
q; - 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;
- int a[N] , pos[N];
- vector<int>tr[N + 5];
- vector
int , 3 > >que[N]; - int vis[N];
- void init(int n){
- for(int i = 0 ; i <= n ; i ++){
- a[i] = 0 , tr[i].clear() , que[i].clear() , vis[i] = 0;
- }
- }
- LL l[N] , r[N] , id[N] , sz[N] , hs[N] , tot = 0 , ans[N];
- set<int>num;
- void dfs(int cur , int f){//重儿子 , 子树大小
- l[cur] = ++ tot;
- id[tot] = cur;//
- sz[cur] = 1;
- hs[cur] = -1;
- for(auto it : tr[cur]){
- if(it != f){
- dfs(it , cur);
- sz[cur] += sz[it];
- if(hs[cur] == -1 || sz[it] > sz[hs[cur]]){
- hs[cur] = it;
- }
- }
- }
- r[cur] = tot;
- }
- void dfs2(int cur , int f , int keep){
- for(auto it : tr[cur]){
- if(it != f && it != hs[cur]){
- dfs2(it , cur , 0);//轻儿子的信息无需保留
- }
- }
- if(hs[cur] != -1){
- dfs2(hs[cur] , cur , 1);
- }
- auto add = [&](int x){
- vis[x] = 1;
- num.insert(pos[x]);
- };
- auto del = [&](int x){
- vis[x] = 0;
- num.erase(pos[x]);
- };
- for(auto it : tr[cur]){
- if(it != f && it != hs[cur]){//轻儿子加入到重儿子当中
- for(int x = l[it] ; x <= r[it] ; x ++){
- if(!vis[id[x]])
- add(id[x]);
- }
- }
- }
- add(cur);
- for(auto it : que[cur]){//QLOGN
- auto p = lower_bound(num.begin() , num.end() , it[0]);
- int x = *p;
- // cout << cur <<" " << it[0] <<" "<< x << endl;
- if(x > it[1] || x < it[0]){
- ans[it[2]] = 0;
- }
- else{
- ans[it[2]] = 1;
- }
- }
- if(!keep){
- for(int x = l[cur] ; x <= r[cur] ; x ++){//NlogN
- del(id[x]);
- }
- }
- }
- void solve()
- {
- cin >> n >> m;
- for(int i = 1 ; i < n ; i++){
- int x , y;
- cin >> x >> y;
- tr[x].pb(y);
- tr[y].pb(x);
- }
- for(int i = 1 ; i <= n ; i ++){
- cin >> a[i];
- pos[a[i]] = i;
- }
- for(int i = 0 ; i < m ; i ++){
- int l , r , x;
- cin >> l >> r >> x;
- que[x].pb({l , r , i});
- }
- dfs(1 , 0);
- dfs2(1 , 0 , 0);
- for(int i = 0 ; i < m ; i ++){
- if(ans[i]){
- cout <<"YES\n";
- }
- else{
- cout <<"NO\n";
- }
- }
- init(n);
- cout << endl;
- num.clear();
- }
- 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;
- }