2022 winter vacation training week1

Posted by EagerWolf on Sun, 16 Jan 2022 21:48:58 +0100

Day 1

AcWing 2041. Haystack

Simple prefix and, plus a little bit of read in optimization

int main()
{
    n = read() , k = read();
    for( int i = 1 , l , r ; i <= k ; i ++ )
    {
        l = read() , r = read();
        a[ l ] ++ , a[ r + 1 ] --;
    }
    for( int i = 1 ; i <= n ; i ++ ) a[i] += a[ i - 1 ];
    sort( a + 1 , a + 1 + n );
    cout << a[ n / 2 + 1  ] << endl;
    return 0;
}

AcWing 2058. Clumsy fingers

Enumeration has only one digit different from a and B

And find the intersection of the two sets

There are 2 or 3 decimal conversion, using the very common Qin Jiushao algorithm

#include <bits/stdc++.h>
using namespace std;

string a , b;
set< int >s;

int get( string d , int k )
{
    int res = 0;
    for( auto c : d )
        res = res * k + c - '0';
    return res;
}

int main()
{
    cin >> a >> b;
    for( auto & c : a )
    {
        c ^= 1;
        s.insert( get( a , 2 ) );
        c ^= 1;
    }

    for( auto & c : b )
    {
        auto t = c;
        for( int i = 0 ; i < 3 ; i ++ )
        {
            if( i + '0' != t )
            {
                c = i + '0';
                int x = get( b , 3 );
                if( s.count(x) )
                {
                    cout << x << endl;
                    return 0;
                }
            }
        }
        c = t;
    }
}

Day 2

AcWing 1987. Painting fence

In essence, it is a difference. Because the data range is relatively large, we naturally need a hash. At the same time, because we need to traverse sequentially, we need to use a map. Here we also use a new feature of c++17

#include <bits/stdc++.h>
using namespace std;

const int N = 1e6 + 5;
int n ;
map< int, int > b;

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 readop()
{
    char ch = getchar();
    while( ch != 'L' && ch != 'R' ) ch = getchar();
    return ( ch == 'R' ) ? 1 : 0 ;
}

int main()
{
    n = read(); 
    for( int x = 0 , y , op ; n ; n -- )
    {
        y = read() , op = readop();
        if( op ) b[x] ++ , b[ x + y ] -- , x += y;
        else b[ x - y ] ++ , b[x] -- , x -= y;
    }
    int res = 0 , sum = 0 , last = 0;
    for( auto&[ x , v ] : b )
    {
        if( sum >= 2 ) res += x - last;
        sum += v , last = x;
    }
    cout << res << endl;
}

AcWing 1978. The cow crossed the road

Let's start with \ (o(n^2) \), which is to use the fast criterion. If one end point of a line is smaller and the other end point is larger, the two lines intersect. This will cause \ (TLE \)

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 5;
int n , a[N] , b[N] , res ;
bool f[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 ++ ) a[i] = read() , b[i] = read();
    memset( f , 1 , sizeof(f) );
    for( int i = 1 ; i <= n ; i ++ )
    {
        for( int j = 1  ; j <= n && f[i] ; j ++ )
        {
            if( i == j ) continue;
            if( ( a[i] <= a[j] && b[i] >= b[j] ) || ( a[i] >= a[j] && b[i] <= b[j] ) ) f[i] = f[j] = 0;
        }
            
    }
    for( int i = 1 ; i <= n ; i ++ ) res += f[i];
    cout << res << endl;
}

In addition to the practice of \ (O(nlog_n) \), sort all points according to \ (a_i \)

Traverse successively. If the maximum prefix value of \ (b \) is smaller than the current value and the minimum suffix value is larger than the current value, this line will not intersect with other lines

#include <bits/stdc++.h>
#define F first
#define S second
using namespace std;

const int N = 1e5 + 5;
int n , res , maxS[N] , minS[N];
pair< int , int > node[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 ++ ) node[i].F = read() , node[i].S = read();
    sort( node + 1 , node + 1 + n );
    maxS[0] = - 0x7f7f7f7f ; for( int i = 1 ; i <= n ; i ++ ) maxS[i] = max( maxS[ i - 1 ] , node[i].S );
    minS[n+1] = 0x7f7f7f7f ; for( int i = n ; i >= 1 ; i -- ) minS[i] = min( minS[ i + 1 ] , node[i].S );
    for( int i = 1 ; i <= n ; i ++ )
        if( maxS[ i - 1 ] < node[i].S && minS[ i + 1 ] > node[i].S ) res ++;
    cout << res << endl;
    return 0;
}

Day 3

AcWing 1969. Variety proximity

First of all, the naked writing method is the direct violence of \ (n^2 \), and the data range is \ (5e4 \)

#include <bits/stdc++.h>
using namespace std;

const int N = 1e6 + 5;
int n , k , id[N] , res = -1;

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 <= n ; i ++ ) id[i] = read();
    for( int i = 1 ; i <= n ; i ++ )
    {
        if( id[i] <= res ) continue;
        for( int j = max( 1 , i - k ) ; j <= min( n , i + k ) ; j ++ )
        {
            if( id[i] != id[j] || i == j ) continue;
            res = id[i];
            break;
        }
    }
    cout << res << endl;
}

Use last [] to record where each id last appeared. If the distance from the current id is less than or equal to k, it is a crowded cow pair

#include <bits/stdc++.h>
using namespace std;

const int M = 5e4 + 5 , N = 1e6 + 5;
int n , k , last[N] , res = -1;

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 , idn; i <= n ; i ++ )
    {
        idn = read();
        if( last[idn] && i - last[idn] <= k ) res = max( res , idn );
        last[idn] = i;
    }
    cout << res << endl;
}

CF#765 div.2

A

Given n numbers, find the minimum sum of 1 under binary after XOR between a number and the N numbers respectively

Count the number of 1 in each bit of all binary numbers. If the number is greater than equal one \ (\ frac{n}{2} \), the bit of res is 1, and vice versa

#include <bits/stdc++.h>
using namespace std;

const int N = 105;
int n , k , res , a[N];

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 slove()
{
    n = read() , k = read() , res = 0;
    for( int i = 1 ; i <= n ; i ++ ) a[i] = read();
    for( int i = 0 , cnt ; i < k ; i ++ )
    {
        cnt = 0;
        for( int j = 1 ; j <= n ; j ++ )
            if( ( a[j] >> i ) & 1 ) cnt ++;
        if( cnt * 2 >= n ) res += ( 1 << i );
    }
    printf("%d\n" , res );
}

int main()
{
    int t = read();
    while( t -- ) slove();
}

B

For a sequence with a given length of \ (n \), it is necessary to ensure that two different subsequences have the same length and at least one corresponding position is equal.

First, save the position of each number and enumerate two numbers arbitrarily. The addition of the prefix of the former number and the suffix length of the latter number is the longest subsequence. For the longest subsequence with the same position, it is easy to know that when two numbers are adjacent, the subsequence is the longest

#include <bits/stdc++.h>
using namespace std;

const int N = 15e4+5;
int n , k , res , maxn;
vector< int > a[N];

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 slove()
{
    n = read() , res = -1;
    for( int i = 0 ; i <= maxn ; i ++ ) a[i].clear();
    maxn = 0;
    for( int i = 1 , x ; i <= n ; i ++ ) x = read() , a[x].push_back( i ) , maxn = max( maxn , x );
    for( int l = 0 ; l <= maxn ; l ++ )
    {
        if( a[l].size() == n )
        {
            cout << n - 1 << endl;
            return ;
        }
        for( int i = 0 , j = 1 ; j < a[l].size() ; i ++ , j ++ )
            res = max( res , a[l][i] + n - a[l][j] );
    }
    cout << res << endl;
    return ;
}

int main()
{
    int t = read();
    while( t -- ) slove();
}

Day4

Niuke Xiaobai monthly race 43

A

m queries, each time give an n query, there are several satisfactory numbers between 1 and n

The definition of a satisfactory number is that after all the factors of each number are sorted from small to large, the last factor can be divided by the middle factor.

#include <bits/stdc++.h>
#define F first
#define S second
using namespace std;

const int N = 1e4 + 5;
int res[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 slove( int t )
{
    vector< int > v; v.push_back(0);
    for( int i = 1 ; i <= t ; i ++ )
        if( t % i == 0 ) v.push_back(i);
    int m = v.size()-1;
    if( v[m] % v[ (m+1)/2 ] == 0  ) return 1;
    else return 0;
}

int main()
{
    for( int i = 1 ; i <= 1000 ; i ++ )
        res[i] = res[i-1] + slove( i );
    int t = read();
    for( int i = 1 , x ; i <= t ; i ++ )
        x = read() , printf( "%d\n" , res[x] );
}

After the game, it was found that each factor with the largest number in all the factors was itself, so it must be divided by all the factors. It was not found in the game because I read the wrong topic at the beginning

With this conclusion, you have the following code.

t = int( input() )
for i in range(0,t):
    print(input())

B

When a or b is equal to t, 0 is directly output without operation

When t is an odd number, there must be no solution, because as long as you operate, you can only get an even number

In other cases, sum=a+b should be greater than or equal to t/2, so keep doubling first. When it is greater than or equal to half, gather up half first and double it

#include <bits/stdc++.h>
#define ll long long
using namespace std;

ll a , b , t , res;

void slove()
{
    cin >> a >> b >> t;
    if( a == t || b == t ) printf("0\n");
    else if( t % 2 ) printf("-1\n");
    else if( a+b >= t/2 ) printf("1\n");
    else
    {
        ll res = 0;
        a += b;
        while( a < t / 2 ) a *= 2 , res ++ ;
        cout << res+1 << endl;
    }
}

int main()
{
    int k;
    cin >> k;
    while( k -- ) slove();
    return 0;
}

Day5

AcWing 1960. twinkle

Because there are only \ (2 ^ {16} = 65536 \) cases at most, the next case of each case is fixed, and \ (B \) can get \ (10 ^ {15} \), so when \ (B \) is large, there must be a ring

For each case, we use a binary number, and then for each bulb, XOR with the bulb on the left is the next case.

Use p [] to record each state. The first occurrence is in the first step. Subtracting the second occurrence from the first is the size of the ring.

#include <bits/stdc++.h>
#define ll long long
using namespace std;

const int N = ( 1 << 16 ) + 5;
ll n , m ;
int p[N];

int update( int state)
{
    int res = 0;
    for( int i = 0 , j , x , y; i < n ; i ++)
    {
        j = ( i - 1 + n ) % n ;
        x = state >> i & 1 , y = state >> j & 1 ;
        res |= ( x ^ y ) << i ;
    }
    return res;
}

void print( int state )
{
    for( int i = 0 ; i < n ; i ++ )
        cout << ( state >> i & 1 ) << endl;
}

int main()
{
    cin >> n >> m;
    int state = 0;
    for( int i = 0 , x ; i < n ; i ++ )
    {
        cin >> x;
        state |= x << i;
    }
    memset(  p , -1 , sizeof(p) );
    p[state] = 0;
    for( int i = 1 ; ; i ++ )
    {
        state = update(state);
        if( i == m ) print(state) , exit(0);
        else if( p[state] == -1 ) p[state] = 0;
        else
        {
            int len = i - p[state] , r = ( m - i ) % len ;
            while( r -- ) state = update(state);
            print(state);
            exit(0);
        }
    }
    return 0;
}

Day 6

AtCoder Beginner Contest 235

A

Check in question

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int a , b = 0;
    cin >> a;
    while(a) b += a % 10 , a /= 10;
    cout << b * 111 << endl;
    return 0;
}

B

Check in question

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int n , res ;
    cin >> n >> res ;
    for( int i = 2 , x ; i <= n ; i ++ )
    {
        cin >> x;
        if( x > res ) res = x;
        else break;
    }
    cout << res << endl;
}

C

The topic is to give me A sequence of A question x where the k-th appears

The positive solution should be hash ed, and then record the position of each number. Here, you can directly use the map vector, but I don't know why unordered_map will be inexplicable

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5+5;
int n , q , cnt;
map< int , vector<int> > h;

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() , q = read();
    for( int i = 1 , x ; i <= n ; i ++ )
        x = read() , h[x].push_back(i);
    for( int i = 1 , x , y ; i <= q ; i ++ )
    {
        x = read() , y = read();
        if( h.find(x) == h.end() ) printf("-1\n");
        else
        {
            if( y > h[x].size() ) printf("-1\n");
            else printf( "%d\n" , h[x][y-1] );
        }
    }
    return 0;
}

D

Given a and n, ask how many times you can multiply a from 1, or you can put it on the top (123456 can be transformed into 612345) and ask how many times you can become a at least

At first, I thought about two-way bfs and ID DFS. Finally, I estimated that bfs and memory method could be completed

However, the problem card long, long, re has been repeated several times without remembering

#include <bits/stdc++.h>
#define ll long long
using namespace std;

const int N = 2e6+1;
int a , n;
ll dis[N+5];
bitset<N+5> vis;
queue<ll>q;

int main()
{
    cin >> a >> n;
    q.push(1) , vis[1] = 1;
    ll x , y;
    string s , t;
    while(q.size())
    {
        x = q.front() , q.pop();
        if( x == n )
        {
            cout << dis[n] << "\n";
            return 0;
        }

        if( x * a < N && !vis[x*a] )
            vis[x*a] = 1 , q.push( x*a ) , dis[x*a] = dis[x] + 1;

        if( (x%10) && (x>10) )
        {
            t = to_string(x);
            s = t.back() + t.substr( 0 , t.size() - 1 );
            y = stoi(s);
            if( y < N && !vis[y] )
                vis[y] = 1 , q.push(y) , dis[y] = dis[x]+1;
        }
    }
    cout << "-1\n";
    return 0;
}

Day 7

AcWing 2060. Cow beauty pageant

The data range is very small. All points in the two spots can be calculated and compared. The complexity is O(nm)

#include <bits/stdc++.h>
#define x first
#define y second
#define ll long long
using namespace std;

const int N = 65;
const int dx[] = { -1 , 0 , 1 , 0 } , dy[] ={ 0 , 1 0 , -1 };
int m , n;
char g[N][N];
vector< pair< int , int > > p[2];


void dfs( int x , int y , vecotr< pair< int , int > > & ps )
{
    g[x][y] = '.' , ps.push_back( { x , y } );
    for( int i = 0 , a , b ; i < 4 ; i ++ )
    {
        a = x + dx[i] , b = y + dy[i];
        if( a >= 0 && a < n && b >= 0 && b < n && g[a][b] == 'X' )
            dfs( a , b , ps );
    }
}

int main()
{
    cin >> n >> m;
    for( int i = 0 ; i < n ; i ++ ) cin >> g[i];

    for( int i = 0 , k = 0 ; i < n ; i ++ )
        for( int j = 0 ; j < m ; j ++ )
            if( g[i][j] == 'X' )
                dfs( i , j , p[ k ++ ] );
    int res = 1e8 + 5;
    for( auto & a : p[0] )
        for( auto & b : p[1] )
            res = min( res , abs( a.x - b.x ) + abs( a.y - b.y ) + 1 );
    cout << res << endl;
}

AcWing 2019. Tractor

Although the total positive solution of y is a two terminal queue bfs, I can also get through it with spfa

The point with haystack is 1, and the other points are 0

#include <bits/stdc++.h>
#define x first
#define y second
using namespace std;

const int N = 1010;

const int dx[4] = {1, 0, -1, 0} , dy[4] = {0, 1, 0, -1};
int n , sx , sy , dis[N][N];
bool st[N][N] ,  g[N][N];

void spfa()
{
    queue< pair<int,int> > q;
    q.push( {sx,sy} ) ,  memset( dis , 0x3f , sizeof( dis ) );
    dis[sx][sy] = 0 , st[sx][sy] =1;
    while ( q.size() )
    {
        pair<int,int>  t = q.front(); q.pop();
        st[t.x][t.y] = 0;
        for (int i = 0 , a ,b ; i < 4; i ++)
        {
            a = t.x + dx[i] , b = t.y + dy[i];
            if (a < 0 || a > N - 1|| b < 0 || b > N - 1) continue;
            if (dist[a][b] > dist[t.x][t.y] + g[a][b])
            {
                dis[a][b] = dis[t.x][t.y] + g[a][b];
                if (!st[t.x][t.y])
                    q.push({a, b}) , st[a][b] = 1;
            }
        }
}

int main()
{
    cin >> n >> sx >> sy;
    for( int i = 0 , x ,y ; i < n ; i ++ ){
        cin >> x >> y;
        g[x][y] = 1;
    }
    spfa();
    cout << dis[0][0] << endl;
}

Topics: XCPC