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;
}
posted @ 2022-03-19 12:36  PHarr  阅读(46)  评论(0编辑  收藏  举报