1. 程式人生 > 其它 >AcWing題目選做

AcWing題目選做

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;
}