One Bamboo Contest Round #13(Clone from 2019 ICPC Yinchuan)

N. Fibonacci Sequence(补队友题)

print("1 1 2 3 5")

B. So Easy(补队友题)

\(x_i\)表示第\(i\)行加的值,\(y_i\)表示第\(i\)列加的值。则有\(a_{i,j}=x_i+y_j\)

\(j-1\) \(j\)
\(i-1\) \(x_{i-1}+y_{j-1}\) \(x_{i-1}+y_j\)
\(i\) \(x_i+y_{j-1}\) \(x_i+y_j\)

所以有\(a_{i,j}=a_{i-1,j}+a_{i,j_1}-a_{i-1,j-1}\)恒成立,当时实际过程种还要再考虑一下边界问题。

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

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(){
    int n = read();
    auto g = vector( n+1 , vector<int>(n+1) );
    for( int i = 1 ; i <= n ; i ++ )
        for( int j = 1 ; j <= n ; j ++ )
            g[i][j] = read();
    int sx = 0 , sy = 0 , tx , ty;
    for( int i = 1 ; sx == 0 && sy == 0 && i <= n ; i ++ )
        for( int j = 1 ; sx == 0 && sy == 0 && j <= n ; j ++ )
            if( g[i][j] == -1 ) sx = i , sy = j;
    if( sx-1 >= 1 ) tx = sx-1;
    else tx = sx+1;
    if( sy-1 >= 1 ) ty = sy-1;
    else ty = sy+1;
    cout << g[sx][ty] + g[tx][sy] - g[tx][ty];

}

I. Base62(补队友题)

这题其实就是进制转换,但是需要高精度,很麻烦,所以我采用了python,这样一来就变成了进制转换的模板了

cti , itc , num = {} , {} , 0
for i in "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz":
    cti[i] = num
    itc[num] = i
    num += 1

x , y , z = input().split(" ")
x = int(x)
y = int(y)
tmp = 0
for i in z :
    tmp = tmp * x + cti[i]
if tmp == 0 :
    print("0")
    exit(0)
res = []
while tmp > 0 :
    t = tmp % y
    tmp //= y
    res.append( itc[t] )
print( "".join(res[::-1]) )

G. Pot!!(补队友题)

\(p|n\)说明\(p\)\(n\)的质因子,\(p^m|n,p^{m+1}\nmid n\)说明\(m\)\(n\)质因数分解后的最高次幂。因为每次乘的数最大是\(10\)所以质因子只有\(2,3,5,7\)

这道题就变成了区间加,区间最值查询。分块写一下就好。

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

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

class Parts{
private:
    struct Part{
        int l , r , max , tag;
        vector<int> val;
        Part( int l , int r , int max , int tag , vector<int> val )
            : l(l) , r(r) , max(max) , tag(tag) , val(val) {};
    };
    int n , t;
    vector<int> pos;
    vector<Part> p;
public:
    Parts( int n ) : n(n){
        t = sqrt(n);
        pos.resize(n+1);
        for( int i = 1 ; i <= t ; i ++ )
            p.push_back( Part( (i-1)*t+1 , i*t , 0 , 0 , vector<int>() ) );
        if( p.back().r < n )
            p.push_back( Part(p.back().r+1 , n , 0 , 0 , vector<int>() ) );
        for( int i = 1 , j = 0 ; i <= n ; i ++ ){
            if( i > p[j].r ) j ++;
            p[j].val.push_back(0) , pos[i] = j;
        }
    }
    void update(int l , int r , int d ){
        for( int i = pos[l] ; i <= pos[r] ; i ++ ){
            if( p[i].l >= l && p[i].r <= r )
                p[i].max += d , p[i].tag += d;
            else{
                for( int j = max( l , p[i].l) - p[i].l ; j <= min( r , p[i].r) - p[i].l ; j ++ )
                    p[i].val[j] += d;
                p[i].max = INT_MIN;
                for( auto & j : p[i].val )
                    j += p[i].tag , p[i].max = max( p[i].max , j );
                p[i].tag = 0;
            }
        }
    }
    int getMax( int l , int r ){
        int res = INT_MIN;
        for( int i = pos[l] ; i <= pos[r] ; i ++ ){
            if( p[i].l >= l && p[i].r <= r )
                res = max( res , p[i].max );
            else{
                for( int j = max(l,p[i].l)-p[i].l ; j <= min(r,p[i].r)-p[i].l ; j ++ )
                    res = max( res , p[i].val[j] + p[i].tag );
            }
        }
        return res;
    }
};


int32_t main(){
    int n = read() , q = read();
    Parts p2(n) , p3(n) , p5(n) , p7(n);
    for( char s[10] ; q ; q -- ){
        scanf("%s" , s );
        if( s[1] == 'U' ){
            int l = read() , r = read() , d = read() , t = 0;
            while( d % 2 == 0 ) d /= 2 , t ++;
            if( t > 0 ) p2.update( l , r , t ) , t = 0;

            while( d % 3 == 0 ) d /= 3 , t ++;
            if( t > 0 ) p3.update( l , r , t ) , t = 0;

            while( d % 5 == 0 ) d /= 5 , t ++;
            if( t > 0 ) p5.update( l , r , t ) , t = 0;

            while( d % 7 == 0 ) d /= 7 , t ++;
            if( t > 0 ) p7.update( l , r , t ) , t = 0;
        }
        else{
            int l = read() , r = read();
            printf("ANSWER %d\n" , max( { p2.getMax(l,r) , p3.getMax(l,r) , p5.getMax(l,r) , p7.getMax(l,r)} ) );
        }
    }
}

H. Delivery Route

其实就是单元最短路,但是因为有负权边不能跑Dijkstra,只能跑SPFA。但是,数据被构造过,直接跑SPFA会TLE。所以这里我们要用一个特殊的性质,就是双向边都是正权值,单向边可能是负权值。所以我们可以先在图中只加入双向边,这样图就是若干个连通块,块内跑Dijkstra,把连通块当作一个点,块外跑SPFA即可。

具体的实现步骤

  1. 首先把双向边都加入,然后跑dfs划分连通块,并且给每个点都标上对应连通块的号c[i],然后对于每个连通块开一个数组part[i]\(O(n)\)的处理出所以的连通块对应的点。
  2. 开数组deg[i]表示第i个联通块的入度,把单向边加入到图中,同时deg[c[v]]++统计所有联通快的入度。
  3. 开队列q,把c[s]放入进去,在把所有入读为零的块放进去
  4. 然后取出队头,开始跑Dijkstra
    1. 把块中所有的点放入的小根堆中
    2. 取出堆顶u,如果被更新过,重复1,否则继续
    3. 枚举所有的边(u,v,w),更新d[v]
    4. 如果c[v]==c[u],说明边在块内,v加入堆中继续做Dijkstra。否则,说明边跨块,deg[c[v]]--,当deg[c[v]]为零时,c[v]加入队列
    5. 重复2~4,直到堆空结束
  5. 重复4,直到队空结束
#include <bits/stdc++.h>
#define int long long
using namespace std;

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

typedef pair<int,int> PII;

const int N = 50005;
bitset<N>vis;
int n , r , p , s , c[N] , tot = 0;
vector<int> dis, deg;
vector<vector<PII>> e;
vector<vector<int>> part;

void dfs( int x , int id ){
    c[x] = id;
    for( auto [ v , w ] : e[x] ){
        if( c[v] ) continue;
        dfs( v , id );
    }
    return;
}

int32_t main(){
    n = read() , r = read() , p = read() , s = read();
    e.resize(n+1);
    for( int u , v , w ; r ; r -- )
        u = read() , v = read() , w = read() , e[u].emplace_back( v , w ) , e[v].emplace_back(u,w);
    for( int i = 1 ; i <= n ; i ++ ) if( c[i] == 0 ) dfs( i , ++ tot );
    deg.resize( tot+1);
    for( int u , v , w ; p ; p -- )
        u = read() , v = read() , w = read() , e[u].emplace_back( v , w ) , deg[ c[v] ] ++;
    part.resize(tot+1);
    for( int i = 1 ; i <= n ; i ++ ) part[ c[i] ].push_back( i );
    queue<int> q; q.push( c[s] );
    for( int i = 1 ; i <= tot ; i ++ ) if( deg[i] == 0 && i != s ) q.push(i);
    dis.resize(n+1) , fill( dis.begin() , dis.end() , INT_MAX ) , dis[s] = 0;
    while( q.size() ){
        auto it = q.front(); q.pop();
        priority_queue< PII , vector<PII> , greater<PII> > heap;
        for( auto i : part[it] ) heap.emplace( dis[i] , i );
        while( heap.size() ){
            auto [ d , u ] = heap.top(); heap.pop();
            if( vis[u] ) continue; vis[u] = 1;
            for( auto [ v , w ] : e[u] ){
                if( d != INT_MAX && dis[v] > d + w ){
                    dis[v] = d + w;
                    if( c[u] == c[v] ) heap.emplace( dis[v] , v );
                }
                if( c[u] != c[v] ){
                    deg[ c[v] ] --;
                    if( deg[ c[v] ] == 0 ) q.push( c[v] );
                }
            }
        }
    }
    for( int i = 1 ; i <= n ; i ++ ) ( dis[i] >= INT_MAX ? printf("NO PATH\n") : printf( "%d\n" , dis[i] ) );
    return 0;
}

F. Function!(补队友题)

posted @ 2023-01-09 10:57  PHarr  阅读(19)  评论(0编辑  收藏  举报