AcWing题目选做

1|01934. 贝茜放慢脚步


一个二路归并,首先要把所有的点分别排序,每次计算当前的是想到下一个时间点还是下一个位置点,选取先到的就好了

#include<bits/stdc++.h> using namespace std; int n; vector<double> a , b; int main() { cin >> n; char op; for( double x ; n ; n -- ) { cin >> op >> x; if( op == 'T' ) a.push_back(x); else b.push_back(x); } b.push_back(1000); sort( a.begin() , a.end() ) , sort( b.begin() , b.end() ); int i = 0 , j = 0; double s = 0 , t = 0 , v = 1; while( i < a.size() || j < b.size() ) if( i < a.size() && ( a[i] - t ) < ( b[j] - s ) * v ) { s += ( a[i] - t ) / v; t = a[i]; i ++ , v ++; } else { t += ( b[j] - s ) * v; s = b[j]; j ++ , v ++; } printf("%.0lf\n" , t ); }

2|01738. 蹄球


首先可以的知道每个点最多只能指向一个点,但是可能被之多两个点指向,也就是说点的出度为一入度小于等于二,也就是一个基环树,同时环最大只能是二,我们要找到所有的根也就是入度为零的点,然后可能存在一些单独环,每个环也算一个

#include<bits/stdc++.h> using namespace std; const int N = 105 , inf = 1e8; int n , a[N] , p[N] , d[N] , res; int main() { cin >> n; for( int i = 1 ; i <= n ; i ++ ) cin >> a[i]; a[0] = - inf , a[n+1] = inf; sort( a + 1 , a + 1 + n ); for( int i = 1 ; i <= n ; i ++ ) if( ( a[i] - a[i-1] ) <= ( a[i+1] - a[i] ) ) p[i] = i - 1 , d[i-1] ++; else p[i] = i + 1 , d[i+1] ++; for( int i = 1 ; i <= n ; i ++ ) if( d[i] == 0 ) res += 2; else if ( p[p[i]] == i && d[i] == 1 && d[p[i]] == 1 ) res += 1; cout << res / 2 << endl; return 0; }

3|01789. 牛为什么过马路 II


统计每个牛的区间,然后枚举所有牛的组合,判断时候有交集

#include<bits/stdc++.h> using namespace std; string s; int a[26][2] , cnt; int main() { cin >> s; for( int i = 1 , t ; i <= 52 ; i ++ ) { t = s[i-1]-'A'; if( a[t][0] ) a[t][1] = i; else a[t][0] = i; } for( int i = 0 ; i < 26 ; i ++ ) for( int j = 0 ; j < 26 ; j ++ ) if( i == j ) continue; else if( a[i][0] < a[j][0] && a[j][0] < a[i][1] && a[i][1] < a[j][1] ) cnt ++; cout << cnt << endl; return 0; }

4|01776. 牛的基因组学


枚举判断,每一位上斑点牛和非斑点牛是否有相同的碱基

package TestDemo; import java.util.Scanner; public class code01 { public static void main(String[] args) { Scanner in = new Scanner(System.in); int n = in.nextInt() , m = in.nextInt(); String [] a = new String[n]; String [] b = new String[n]; for( int i = 0 ; i < n ; i ++ ){ a[i] = in.next(); } for( int i = 0 ; i < n ; i ++){ b[i] = in.next(); } int res = 0; for( int c = 0 , flag = 1 ; c < m ; flag = 1 , c ++ ){ int [] cnt = new int[26]; for( int r = 0 ; r < n ; r ++ ){ cnt[ a[r].charAt(c) - 'A' ] = 1; } for( int r = 0 ; r < n ; r ++ ){ if (cnt[ b[r].charAt(c) - 'A' ] == 1){ flag = 0; break; } } res += flag; } System.out.println(res); } }

5|01762. 牛的洗牌


这题就是考读题的吧,读题读错了,就是每次做交换就好了

#include<bits/stdc++.h> using namespace std; const int N = 105; int n , a[N] , val[N] , cur[N]; int main() { cin >> n; for( int i = 1 ; i <= n ; i ++ ) cin >> a[i]; for( int i = 1 ; i <= n ; i ++ ) cin >> val[i]; for( int t = 1 ; t <= 3 ; t ++ ) { for( int i = 1 ; i <= n ; i ++ ) cur[i] = val[ a[i] ]; for( int i = 1 ; i <= n ; i ++ ) val[i] = cur[i]; } for( int i = 1 ; i <= n ; i ++ ) cout << val[i] << '\n'; return 0; }

6|01750. 救生员


这道题就是用差分来维护,因为数据范围很小直接暴力做就好了

#include<bits/stdc++.h> #define ll long long using namespace std; const int N = 105 , M = 1005; int n , m , l[N] , r[N] , b[M] , res , sum , 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 ++ ) l[i] = read() , r[i] = read() , m = max( r[i] , m ) , b[ l[i] ] ++ , b[ r[i] ] -- ; for( int i = 1 ; i <= n ; i ++ ) { b[ l[i] ] -- , b[ r[i]] ++ ; sum = ans = 0; for( int j = 0 ; j < m ; j ++ ) sum += b[j] , ans += ( sum > 0 ); res = max( res , ans ); b[ l[i] ] ++ , b[ r[i] ] --; } cout << res << endl; }

7|01715. 桶列表


这里的桶的标号是无效信息,我们只要统计出每一时刻的说需要桶的数量并取最大值就行了

#include<bits/stdc++.h> #define ll long long using namespace std; const int N = 105 , M = 1005; int n , m , b[M] , res ; 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 , l , r , v ; i <= n ; i ++ ) l = read() , r = read() , v = read() , b[l] += v , b[r+1] -= v , m = max( m , r ); for( int i = 1 ; i <= m ; i ++ ) b[i] += b[i-1] , res = max( res , b[i] ); cout << res << endl; return 0; }

8|01443. 拍照


因为有a[i] = b[i-1] - a[i-1],所以只要枚举出a[1]就可以递推出完整的序列

然后要保证a[i][1,n]中且不能重复即可

#include<bits/stdc++.h> #define ll long long using namespace std; const int N = 1e3+5; int n , a[N] , b[N]; bitset<N> vis; 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 ++ ) b[i] = read(); for( a[1] = 1 ; ; a[1]++ ) { vis.reset() , vis[ a[1] ] = 1; int f = 1; for( int i = 2 ; i <= n && f ; i ++ ) { a[i] = b[i-1] - a[i-1]; if( a[i] < 1 || a[i] > n ) f = 0; else if ( vis[ a[i] ] ) f = 0; else vis[ a[i] ] = 1; } if( !f ) continue; for( int i = 1 ; i <= n ; i ++ ) cout << a[i] << ' '; cout << endl; return 0; } return 0; }

9|01672. 疯狂的科学家


因为一定有最有解满足所有的集合都不想交,所以用双指针扫一遍就好

#include<bits/stdc++.h> #define ll long long using namespace std; const int N = 1005; int n , cnt; string a,b; int main() { cin >> n >> a >> b; for( int i = 0 , j ; i < n ; i ++ ) { if( a[i] != b[i] ) { j = i + 1; while( j < n && a[j] != b[j] ) j ++; cnt ++ , i = j; } } cout << cnt << endl; return 0; }

10|01660. 社交距离 II


如果要保证源头最少就要保证他的传染范围最大,所以先排序,然后通过便利查找相邻的感染与未感染间距的最小值,这个值减一就是传染的最大距离,我们可以通过双指针扫出有多少个感染源

#include<bits/stdc++.h> #define ll long long using namespace std; const int N = 1005; int n , MaxRange = 1e7 + 5 , res; pair< int , int > p[N]; inline int read() { int x = 0 , f = 1 , ch = getchar(); while( (ch < '0' || ch > '9') && ch != '-' ) ch = getchar(); if( ch == '-' ) f = -1 , ch = getchar(); while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar(); return x * f; } int main() { n = read(); for( int i = 1 ; i <= n ; i ++ ) p[i].first = read() , p[i].second = read(); sort( p + 1 , p + 1 + n ); for( int i = 2 ; i <= n ; i ++ ) { if( p[i].second == p[i-1].second ) continue; MaxRange = min( MaxRange , p[i].first - p[i-1].first - 1 ); } for( int i = 1 , j ; i <= n ; i ++ ) if( p[i].second == 1 ){ res ++; j = i + 1; while( j <= n && p[j-1].first + MaxRange >= p[j].first ) j ++; i = j - 1; } cout << res << endl; return 0; }

11|01471. 牛奶工厂


这道题可以用Floyd来维护一下,然后把所有的点便利一遍

#include<bits/stdc++.h> #define ll long long using namespace std; const int N = 105; int n , cnt; int vis[N][N]; inline int read() { int x = 0 , f = 1 , ch = getchar(); while( (ch < '0' || ch > '9') && ch != '-' ) ch = getchar(); if( ch == '-' ) f = -1 , ch = getchar(); while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar(); return x * f; } int main() { n = read(); for( int i = 1 , u , v ; i < n ; i ++ ) u = read() , v = read() , vis[u][v] = 1; for( int i = 1 ; i <= n ; i ++ ) vis[i][i] = 1; for( int k = 1 ; k <= n ; k ++ ) for( int i = 1 ; i <= n ; i ++ ) for( int j = 1 ; j <= n ; j ++ ) { if( vis[i][j] ) continue; if( vis[i][k] && vis[k][j] ) vis[i][j] = 1; } for( int i = 1 ; i <= n ; i ++ ) { cnt = 0; for( int j = 1 ; j <= n ; j ++ ) cnt += vis[j][i]; if( cnt == n ) printf("%d\n", i ) , exit(0); } printf("-1\n"); return 0; }

12|01929. 镜子田地


通过分析可知每个边界点只有一条边,非边界点有两条边,这样可以知道图的每一个联通块一定是一个环或链,因为边界点都在链上,所以从每一个边界点便利一遍找出最长链即可

#include<bits/stdc++.h> using namespace std; const int N = 1005; const int dx[4] = {-1 , 0 , 1 , 0 } , dy[4] = { 0 , 1 , 0 , -1 }; int n , m ; char g[N][N]; int dfs( int x , int y , int d )// d 是方向 { if( x < 0 || y < 0 || x >= n || y >= m ) return 0; if( g[x][y] == '/' ) d ^= 1; else d ^= 3; return dfs( x + dx[d] , y + dy[d] , d ) + 1; } int main() { cin >> n >> m; for( int i = 0 ; i < n ; i ++ ) cin >> g[i]; int res = 0; for( int i = 0 ; i < n ; i ++ ) res = max( res , dfs(i,0,1) ) , res = max( res , dfs( i , m-1 , 3) ); for( int i = 0 ; i < m ; i ++ ) res = max( res , dfs( n , i , 2 ) ) , res = max( res , dfs( n-1 , i , 0 ) ); cout << res << endl; }

13|01460. 我在哪?


题目让我找一最短多长的字符串所有子串不重复,可以用二分来枚举子串的长度,然后把所有的子串放在set中判重即可,但是由于字符串截取很慢可以中字符串的hash来解决一下

#include<bits/stdc++.h> #define ll long long using namespace std; const int N = 105 , mod = 1e9+7; int res , n ; ll h[N] , p[N]; string s; ll Hash( int l , int r ){ return ( h[r] - h[l-1] * p[r-l+1] % mod + mod ) % mod; } bool check( int len ){ set<int> st; for( int i = 1 , key ; i <= n - len + 1 ; i ++ ) { key = Hash( i , i+len-1 ); if( st.count( key) ) return 0; st.insert(key); } return 1; } int main() { cin >> n >> s; p[0] = 1; for( int i = 1 ; i <= n ; i ++ ) h[i] = ( h[i-1]*26 + s[i-1] - 'A' ) % mod , p[i] = ( p[i-1] * 26 ) % mod; int l = 1 , r = n , mid; while( l <= r ) { mid = ( l + r ) >> 1; if( check(mid) ) res = mid , r = mid - 1; else l = mid + 1; } cout << res << endl; }

14|01696. 困牛排序


每一个点至多用一次操作就可以放在正确的位置上,若操作一个点,必须把前面所的点都操作一次,所以要找到最后一个逆序的

#include<bits/stdc++.h> using namespace std; const int N = 105; int n , a[N]; int main() { cin >> n; for (int i = 1; i <= n; i ++ ) cin >> a[i]; for( int i = n-1 ; i >= 1 ; i -- ) if( a[i] > a[i+1] ) { cout << i << endl; return 0; } cout << "0\n"; return 0; }

__EOF__

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