2022寒假训练week6

1|0Day1-4


1|1AcWing 1843. 圆形牛棚


数据范围很小直接枚举起点就好

#include <bits/stdc++.h> using namespace std; const int N = 1005; int n , a[N] , res = 0x7f7f7f7f; int main() { cin >> n; for (int i = 1; i <= n ; i ++ ) cin >> a[i]; for( auto i = 1 , sum = 0 ; i <= n ; sum = 0 , i ++ ) { for( int j = i + 1 ; j <= n ; j ++ ) sum += a[j] * (j-i); for( int j = 1 ; j < i ; j ++ ) sum += a[j] * ( n - i + j ); res = min( res , sum ); } cout << res << endl; }

1|2AcWing 1855.愤怒的奶牛


数据很小就暴力做,每次枚举一点把他放到set中
只要set没有空就把取出两侧的点并算出新的爆炸范围,然后判断剩下的点是否在爆炸范围中

#include <bits/stdc++.h> using namespace std; const int N = 105; int n , res; set<int> a , b , c ; int main() { cin >> n; for( x ; n ; n -- ) { cin >> x; a.insert(x); } for( auto it : a ) { b = a , b.erase(it) , c.insert(it); int t = 1 , cnt = 1; while( c.size() ) { int l = (*c.begin() )-t , r = (*c.rbegin())+t; t ++ , c.clear(); for( auto ct : b ) if( ct >= l && ct <= r ) c.insert(ct); cnt += c.size(); for( auto ct : c ) b.erase(ct); } res = max( res , cnt ); } cout << res << endl; }

1|3AcWing 1801. 蹄子剪刀布


可以任意规定1,2,3的获胜情况,然后把所有的映射情况枚举一遍就好

#include <bits/stdc++.h> #define F first #define S second using namespace std; const int N = 105; int n , a[N] , b[N] , res; int p[6][4] = { {0,1,2,3}, {0,1,3,2}, {0,2,1,3}, {0,2,3,1}, {0,3,1,2}, {0,3,2,1}, }; inline bool judge( int x , int y ) { if( x == 1 && y == 2 ) return 1; if( x == 2 && y == 3 ) return 1; if( x == 3 && y == 1 ) return 1; return 0; } int main() { cin >> n; for (int i = 1; i <= n; i++) cin >> a[i] >> b[i]; for (int j = 0 , cnt = 0 ; j < 6 ; cnt = 0 , j++) { for (int i = 1; i <= n; i++ ) if( judge(p[j][a[i]] , p[j][b[i]] ) ) cnt ++; res = max( res , cnt ); } cout << res << endl; }

1|4AcWing 3347. 菊花链


做一遍前缀和,在枚举一遍端点,算出平均值,在遍历一边就行

#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N = 105; int n , p[N] , res; int main() { cin >> n; for( int i = 1 ; i <= n ; i ++ ) { cin >> p[i]; p[i] += p[i-1]; } for( int i = 1 , m ; i <= n ; i ++ ) for( int j = i ; j <= n ; j ++ ) { if( ( p[j] - p[i-1] ) % (j-i+1) ) continue; m = ( p[j] - p[i-1] ) / (j-i+1); for( int k = i ; k <= j ; k ++ ) { if(p[k] - p[k-1] == m ) { res ++; break; } } } ; cout << res << endl; return 0; }

1|5AcWing 1826. 农田缩减


我们可以通过枚举每个点来确定边界,如果去掉的本身不在别边界上就不会对答案造成影响,所以我们可以先预处理出当前的边界

#include <bits/stdc++.h> #define X first #define Y second using namespace std; #define PII pair<int,int> const int inf = 0x7f7f7f7f , N = 5e4+5; int n ,x[N] , y[N] , a[N] , b[N] , res = inf; int main() { cin >> n; for( int i = 1 ; i <= n ; i ++ ) { cin >> x[i] >> y[i]; a[i] = x[i] , b[i] = y[i]; } sort( a+1 , a +1+n ) , sort( b+1 , b+1+n ); for( int i = 1 ; i <= n ; i ++ ) { int x1 , x2 , y1 , y2; x1 = x[i] == a[1] ? a[2] : a[1]; x2 = x[i] == a[n] ? a[n-1] : a[n]; y1 = y[i] == b[1] ? b[2] : b[1]; y2 = y[i] == b[n] ? b[n-1] : b[n]; res = min( res , ( x2-x1)*(y2-y1) ); } cout << res << endl; }

1|6AcWing 1813. 方块游戏


贪心的确定每一张卡牌的每个字母可能用到的最大值

#include <bits/stdc++.h> using namespace std; const int N = 30; int n , p[N] , t1[N] , t2[N]; string s1 , s2; int main() { cin >> n; for( int i = 1 ; i <= n ; i ++ ) { cin >> s1 >> s2; memset( t1 , 0 , sizeof(t1) ) , memset( t2 , 0 , sizeof(t2) ); for( auto it : s1 ) t1[it-'a']++; for( auto it : s2 ) t2[it-'a']++; for( int i = 0 ; i < 26 ; i ++ ) p[i] += max( t1[i] , t2[i] ); } for( int i = 0 ; i < 26 ; i ++ ) cout << p[i] << endl; return 0; }

2|0Day 5


2|1AcWing 周赛 39


3|0Day 6


3|12022 天梯模拟赛


A 迷子のCDケース

这道题其实不算难,就是不断的做swap就好,因为数据范围很小可以直接暴力找

#include <bits/stdc++.h> #define F first #define ll long long #define S second using namespace std; inline int read() { int x = 0 , ch = getchar(); while( ch < '0' || ch > '9' ) ch = getchar(); while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar(); return x; } const int N = 105; int n , a[N] , m , t = 0 , b[N] ; int main() { n = read() , m = read(); for( int i = 1 ; i <= n ; i ++ ) a[i] = i; for( int i = 1 , x ; i <= m ; i ++ ) { x = read(); for( int j = 1 ; j <= n ; j ++ ) { if( a[j] != x ) continue; swap( a[j] , a[0] ); break; } } for( int i = 1 ; i <= n ; i ++ ) printf("%d\n" , a[i] ); }

B ゴールドラッシュ

挨个去max相加就行

#include <bits/stdc++.h> #define F first #define ll long long #define S second using namespace std; inline int read() { int x = 0 , ch = getchar(); while( ch < '0' || ch > '9' ) ch = getchar(); while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar(); return x; } const int N = 10; int a[N] , b[N] , res; int main() { int n = 7; for( int i = 1 ; i <= n ; i ++ ) a[i] = read(); for( int i = 1 , x ; i <= n ; i ++ ) x = read() , res += max( a[i] , x ); cout << res << endl; }

C 心配性な富豪、ファミリーレストランに行く。

排个序就好了

#include <bits/stdc++.h> #define F first #define ll long long #define S second using namespace std; inline int read() { int x = 0 , ch = getchar(); while( ch < '0' || ch > '9' ) ch = getchar(); while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar(); return x; } const int N = 105; int n , a[N] ; int main() { scanf("%d",&n); for(int i = 1;i <=n;i++) a[i] = read(); sort( a+1 , a+1+n); for(int i=n-1;i>=1;i--) { if(a[i]!=a[i+1]) { printf("%d\n",a[i]); return 0; } } return 0; }

D Get Your Wish

其实也是很暴力的做就行,但是这道题坑点就是水滴不只有一个

#include<bits/stdc++.h> using namespace std; const int N = 105; int n , m , sx ,sy , dx , dy ; char c; bool f[N][N] , v[N][N]; inline int read() { int x = 0 , ch = getchar(); while( ch < '0' || ch > '9' ) ch = getchar(); while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar(); return x; } int main() { n = read() , m = read(); cin >> c; if( c == '>' ) dx = 0 , dy = 1; else if( c == '<' ) dx = 0 , dy = -1; else if( c == '^' ) dx = -1 , dy = 0; else dx = 1 , dy = 0; for( int i = 1 ; i <= n ; i ++ ) { for( int j = 1 ; j <= m ; j ++ ) { c = getchar(); while( c != '.' && c != 'x' && c != 'o' ) c = getchar(); if( c == 'o' ) { sx = i , sy = j; while( sx >= 1 && sy >= 1 && sx <= n && sy <= m ) { v[sx][sy] = 1; sx += dx , sy +=dy; } } else if( c == 'x' ) f[i][j] = 1; } } for( int i = 1 ; i <= n ; i ++ ) for( int j = 1 ; j <= m ; j ++ ) if( f[i][j] && v[i][j] ) printf("GG\n") , exit(0); printf("OK\n"); return 0; }

E 双生独白

这里牵扯到问提就是进制转换的问提了,Python自带丰富的进制转换问题,这里牵扯的问题就是16进制字符串转换成十进制的数字

n = int(a,16)这样就做好了,还有就是输出十六进制虽然可以转化成字符串在输出实际上可以直接进行格式化输出就好了print("{:02X}".format(n))

n = input() R = n[1:3] G = n[3:5] B = n[5:7] r = 255-int(R,16) b = 255-int(B,16) g = 255-int(G,16) print("#{:02X}{:02X}{:02X}".format(r,g,b) );

F Switches

这里因为灯和开关的数量都比较少,所以就直接用dfs枚举出所有的组合情况,然后判断就行

#include<bits/stdc++.h> using namespace std; const int N = 15; int n , m , a[N] , p[N] , res; vector<int>s[N]; inline int read() { int x = 0 , ch = getchar(); while( ch < '0' || ch > '9' ) ch = getchar(); while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar(); return x; } bool check() { for( int i = 1 ; i <= m ; i ++ ) if( p[i] & 1 ) return 0; return 1; } void dfs( int step ) { if( step > n ) { if(check()) res ++; return ; } dfs( step + 1 ); for( auto it : s[step] ) p[it]++; dfs( step + 1 ); for( auto it : s[step] ) p[it]--; } int main() { n = read() , m = read(); for( int i = 1 , x , k ; i <= m ; i ++ ) { k = read(); for( ; k ; k -- ) x = read() , s[x].push_back(i); } for( int i = 1 ; i <= m ; i ++ ) p[i] = read(); dfs( 1 ); cout << res << endl; return 0; }

G 合并果子

合并果子就是做一个贪心就好了,直接把所有的果子丢进小根堆,然后每次取出最小的两个合并再丢回去

#include<bits/stdc++.h> using namespace std; int n , res; priority_queue<int , vector<int> , greater<int> >q; inline int read() { int x = 0 , ch = getchar(); while( ch < '0' || ch > '9' ) ch = getchar(); while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar(); return x; } int main() { n = read(); for(int i=1 , x ; i<=n ; i++ ) x = read() , q.push(x); int a , b; while( q.size() > 1 ) { a = q.top() , q.pop(); b = q.top() , q.pop(); res += a + b ; q.push( a + b ); } cout << res << endl; return 0; }

H 洛谷团队训练VS传统团队训练

对于洛谷训练比较简单可以直接用公式计算,对于传统的训练就是做一遍统计先统计每个人需要更新几次成绩表,同时再统计下每个人每道题提交了几次,然后对于每道题枚举一下每个人判断是在教师机快还是在学生机快就行

#include<bits/stdc++.h> #define ll long long using namespace std; const int N = 1005; int n , m , ta , tb ,tc , td , A , H , E , R ; int sub[N][N] , sco[N][N]; //submit , score map<int,int> pro , stu; ll luogu , cena; inline int read() { int x = 0 , ch = getchar(); while( ch < '0' || ch > '9' ) ch = getchar(); while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar(); return x; } int main() { n = read() , m = read(); for( int i = 1 , x ; i <= n ; i ++ ) x = read() , pro[x] = i; for( int i = 1 , x ; i <= m ; i ++ ) x = read() , stu[x] = i; ta = read() , tb = read() , tc = read() , td = read() , A = read() , H = read() , E = read(); R = read(); luogu = (n*ta+R*tc)*100.0 / A + H , cena = n*ta; for( int pr , st , sc ; R ; R -- ) { pr = read() , st = read() , sc = read(); pr = pro[pr] , st = stu[st] , sub[st][pr] ++; if( E && sc > sco[st][pr] ) sco[st][pr] = sc , cena += td; } for( int i = 1 ; i <= m ; i ++ ) for( int j = 1 ; j <= n ; j ++ ) cena += min( tb*sub[i][j] , ta + tc*sub[i][j] ); cout << cena << '\n' << luogu << '\n'; if( luogu < cena ) printf("Use Luogu!\n"); else printf("Forget it...\n"); return 0; }

I 「物理」平抛运动

这道题就是简单的高中物理题目,计算的时候注意一下就好

vx=vsinθ=xt,vy=vcosθ=12gt2

import math v , a = map(float ,input().split(' ')) vx = v * math.sin(a) vy = v * math.cos(a) t = vy/ 10.0 y = 5 * t * t x = vx * t print(x,y)

K 车的攻击

其实车所在的位置是不重要的,重要的是车占据了几行几列,所以分别用两个数组存储每个车在哪一行那一列,然后排序去重就知道了,知道行列后答案就是n(r+c)rc

#include<bits/stdc++.h> #define ll long long using namespace std; const int N = 1e6+5; ll n , r , c; int k , a[N] , b[N]; inline int read() { int x = 0 , ch = getchar(); while( ch < '0' || ch > '9' ) ch = getchar(); while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar(); return x; } int main() { n = read() , k = read(); for( int i = 1 ; i <= k ; i ++ ) a[i] = read() , b[i] = read(); sort( a+1 , a+1+k ) , sort( b+1 , b+1+k ); r = unique( a+1 , a+1+k ) - a-1 , c = unique( b+1 , b+1+k ) - b-1; cout << n*(r+c) - r*c << endl; return 0; }

L 售票

数据很小直接暴力的判断就好

#include<bits/stdc++.h> #define ll long long using namespace std; string t[4] = { "***ABCDE", "FGHIJKLM", "NOPQRSTU", "VWXYZ***"}; string s[55] , cur; int n , m; bool f[30]; inline int read() { int x = 0 , ch = getchar(); while( ch < '0' || ch > '9' ) ch = getchar(); while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar(); return x; } int main() { cin >> n; for( int i = 1 ; i <= n ; i ++ ) cin >> s[i]; cin >> cur; m = cur.size(); for( int i = 1 , fa = 1 ; i <= n ; i ++ , fa = 1 ) { if( s[i].size() <= m ) continue; for( int j = 0 ; j < m ; j ++ ) { if( cur[j] == s[i][j] ) continue; fa = 0; break; } if( fa ) f[ s[i][m]-'A' ] = 1; } for( int i = 0 ; i < 4 ; i ++ ) { for( int j = 0 ; j < 8 ; j ++ ) { if(t[i][j] == '*' ) printf("*"); else if( f[t[i][j]-'A'] ) cout << t[i][j]; else printf("*"); } cout << "\n"; } }

N Balanced Photo G

先把所有的牛离散化一下,然后排个序,从左侧开始遍历,因为排序所以可以通过位置计算一共有多少牛比当前牛高,然后在用一个树状数组维护当左侧牛的情况就可以用计算出左侧有多少个牛比当前牛高,一减就是右侧,然后判断就好,最后把当前牛加入到树状数组中

#include<bits/stdc++.h> #define ll long long #define lowbit(x) ( x & -x ) using namespace std; const int N = 1e5+5; int n , a[N] , b[N] , c[N] , res; void update( int x ) { for( int i = x ; i <= n ; i += lowbit(i) ) c[i] ++; } int get( int x ) { int ans = 0; for( int i = x ; i ; i -= lowbit(i) ) ans += c[i]; return ans; } inline int read() { int x = 0 , ch = getchar(); while( ch < '0' || ch > '9' ) ch = getchar(); while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar(); return x; } int main() { n = read() ; for( int i = 1 ; i <= n ; i ++ ) a[i] = b[i] = read(); sort( b + 1 , b + 1 + n ); for( int i = 1 , t , l , r ; i <= n ; i ++ ) { t = lower_bound( b+1 , b+1+n , a[i] ) - b; l = i - 1 - get( t-1 ) , r = n - t - l ; if( r > l ) swap( l , r ); if( l > 2*r ) res ++; update(t); } cout << res << "\n"; return 0; }

O TOU-Tour de Byteotia

首先把所有的两个点都大于k的边加到并查集中,然后开始枚举剩下的边,如果这条边加进去会形成环就不能加,计数器加一否则就是加入到并查集计数器就是答案

为什么要这么做呢?因为如果形成了环只要断掉一条边就行,至于断掉那条边无所谓,因为贡献是相同的

#include<bits/stdc++.h> #define ll long long #define lowbit(x) ( x & -x ) using namespace std; const int N = 1e6+5; int n , fa[N] , cnt , m , k ; vector<pair<int,int>> e; int getfa( int x ) { if( fa[x] == x ) return x; return fa[x] = getfa( fa[x] ); } void merge( int x , int y ) { x = getfa(x) , y = getfa(y); fa[x] = y; } inline int read() { int x = 0 , ch = getchar(); while( ch < '0' || ch > '9' ) ch = getchar(); while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar(); return x; } int main() { n = read() , m = read() , k = read(); for( int i = 1 ; i <= n ; i ++ ) fa[i] = i; for( int i = 1 , u , v ; i <= m ; i ++ ) { u = read() , v = read(); if( u > k && v > k ) merge(u , v); else e.push_back({u,v}); } for(auto [u,v] : e ) { if( getfa(u) == getfa(v) ) cnt ++; else merge(u , v); } cout << cnt << endl; return 0; }

3|2AtCoder Beginner Contest 239


A Horizon

按照题目要求输出就好

import math n = float(input()) print( math.sqrt(n*(12800000+n) ) )

B Integer Division

利用python整除的性质就好

import math n = int(input()) print(n//10)

C Knight Fork

先把第一个点所有的距离为根号五的点放进一个set中,在枚举第二点是否有距离为根号五的点在集合中就好

#include <bits/stdc++.h> #define F first #define ll long long #define S second using namespace std; const ll d[2][2] = { {1,2} , {2,1} } , t[4][2] = { {1,1} , {1,-1} , {-1,1} , {-1,-1}}; ll x_1 , x_2 , y_1 ,y_2; set<pair<ll,ll>> s; int main() { cin >> x_1 >> y_1 >> x_2 >> y_2; for( int i = 0 ; i < 2 ; i ++ ) for( int j = 0 ; j < 4 ; j ++ ) s.insert( { x_1 + d[i][1] * t[j][1] , y_1 + d[i][0] * t[j][0] } ); for( int i = 0 ; i < 2 ; i ++ ) for( int j = 0 ; j < 4 ; j ++ ) if( s.count( { x_2 + d[i][1] * t[j][1] , y_2 + d[i][0] * t[j][0] } ) ) printf("Yes\n"), exit(0); printf("No\n"); return 0; }

D Prime Sum Game

先跑一遍线性筛,然后分别枚举两个人出的数看时候能找到高桥说一个数,青木无论说几和都是素数

#include <bits/stdc++.h> #define F first #define ll long long #define S second using namespace std; const int N = 205; int n , a , b , c , d; int p[N] , cnt ; bool v[N]; void prime( int x ) { for( int i = 2 ; i <= x ; i ++ ) { if(!v[i] ) p[ ++cnt ] = i; for( int j = 1 ; j <= cnt , i * p[j] <= x ; j ++ ) { v[ i*p[j] ] = 1; if( i % p[j] == 0 ) break; } } } int main() { cin >> a >> b >> c >> d ; prime( b + d ); for( int i = a , fa = 1 ; i <= b ; i ++ , fa = 1 ) { for( int j = c ; j <= d && fa ; j ++ ) fa = v[i+j]; if(fa) printf("Takahashi\n") , exit(0); } printf("Aoki\n"); return 0; }

4|0Day 7


4|1AtCoder Beginner Contest 240


A Edge Checker

差绝对值为1或(1,10)的情况相邻

import math a , b = map(int,input().split(' ')) if a > b : a,b = b,a if (b - a) == 1 or ( a == 1 and b == 10 ): print("Yes") else : print("No")

B Count Distinct Integers

用set去冲就好了

#include <bits/stdc++.h> using namespace std; const int N = 30; int n ; set<int> s; int main() { cin >> n; for( int x ; n ; n -- ) { cin >> x; s.insert(x); } cout << s.size() << endl; return 0; }

C Jumping Takahashi

dfs加上一些剪枝,首先保证a[i]<b[i]然后分别对a,b做前缀和,如果当前点的距离加后面的最小值小于X或加后面的最大值大于X则不可行剪掉,然后在做一个记忆化就好

#include <bits/stdc++.h> using namespace std; const int N = 105; int n , m , a[N] , b[N] , c[N] , d[N]; bool f[N][10005]; inline int read() { int x = 0 , ch = getchar(); while( ch < '0' || ch > '9' ) ch = getchar() ; while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar(); return x; } void dfs( int t , int dis ) { if( t > n ) { if( dis == m ) printf("Yes\n") , exit(0); return ; } if( f[t][dis] ) return ; f[t][dis] = 1; if( dis >= m || dis + c[n] - c[t-1] > m || dis + d[n] - d[t-1] < m ) return ; if( dis + c[n] - c[t-1] == m || dis + d[n] - d[t-1] == m ) printf("Yes\n") , exit(0); dfs( t + 1 , dis + a[t] ) , dfs( t + 1 , dis + b[t] ); return ; } int main() { n = read() , m = read(); for( int i = 1 ; i <= n ; i ++ ) { a[i] = read() , b[i] = read(); if( a[i] > b[i] ) swap( a[i] , b[i] ); c[i] = a[i] + c[i-1] , d[i] = b[i] + d[i-1]; } if( c[n] > m || d[n] < m ) printf("No\n") , exit(0); if( c[n] == m || d[n] == m ) printf("Yes\n") , exit(0); dfs(1,0); printf("No\n"); }

D Strange Balls

虽然要做栈,当时要直接把相邻的相同的进行合并,然后按照题目模拟就好

#include <bits/stdc++.h> using namespace std; const int N = 2e5+5; int n , tp , sum; int s[N] , cnt[N] ; inline int read() { int x = 0 , ch = getchar(); while( ch < '0' || ch > '9' ) ch = getchar() ; while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar(); return x; } int main() { n = read(); s[0] = -1; for( int x ; n ; n -- ) { x = read(); if( x == s[tp] ) { if( x == cnt[tp]+1 ) sum -= cnt[tp] , tp --; else sum ++ , cnt[tp] ++; } else sum ++ , s[++tp] = x , cnt[tp] = 1; printf("%d\n" , sum ); } }

4|2Codeforces Round #772 (Div. 2)


现在比赛还没开始,2月21日补题解


__EOF__

本文作者PHarr
本文链接https://www.cnblogs.com/PHarr/p/15916732.html
关于博主:前OIer,SMUer
版权声明CC BY-NC 4.0
声援博主:如果这篇文章对您有帮助,不妨给我点个赞
posted @   PHarr  阅读(56)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示