AcWing題目選做
阿新 • • 發佈:2022-03-19
1934. 貝茜放慢腳步
一個二路歸併,首先要把所有的點分別排序,每次計算當前的是想到下一個時間點還是下一個位置點,選取先到的就好了
#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 ); }
1738. 蹄球
首先可以的知道每個點最多隻能指向一個點,但是可能被之多兩個點指向,也就是說點的出度為一入度小於等於二,也就是一個基環樹,同時環最大隻能是二,我們要找到所有的根也就是入度為零的點,然後可能存在一些單獨環,每個環也算一個
#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; }
1789. 牛為什麼過馬路 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; }
1776. 牛的基因組學
列舉判斷,每一位上斑點牛和非斑點牛是否有相同的鹼基
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);
}
}
1762. 牛的洗牌
這題就是考讀題的吧,讀題讀錯了,就是每次做交換就好了
#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;
}
1750. 救生員
這道題就是用差分來維護,因為資料範圍很小直接暴力做就好了
#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;
}
1715. 桶列表
這裡的桶的標號是無效資訊,我們只要統計出每一時刻的說需要桶的數量並取最大值就行了
#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;
}
1443. 拍照
因為有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;
}
1672. 瘋狂的科學家
因為一定有最有解滿足所有的集合都不想交,所以用雙指標掃一遍就好
#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;
}
1660. 社交距離 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;
}
1471. 牛奶工廠
這道題可以用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;
}
1929. 鏡子田地
通過分析可知每個邊界點只有一條邊,非邊界點有兩條邊,這樣可以知道圖的每一個聯通塊一定是一個環或鏈,因為邊界點都在鏈上,所以從每一個邊界點便利一遍找出最長鏈即可
#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;
}
1460. 我在哪?
題目讓我找一最短多長的字串所有子串不重複,可以用二分來列舉子串的長度,然後把所有的子串放在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;
}
1696. 困牛排序
每一個點至多用一次操作就可以放在正確的位置上,若操作一個點,必須把前面所的點都操作一次,所以要找到最後一個逆序的
#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;
}