牛客小白月赛64
A.小杜要迟到了!
#include <bits/stdc++.h>
#define int long long
using namespace std;
int32_t main(){
int n , k , a , b , r1 , r2;
cin >> n >> k >> a >> b;
n -- , k --;
r1 = ( n + k ) * b;
r2 = n * a;
if( r1 < r2 ) cout << 1;
else if( r1 > r2 ) cout << 2;
else cout << 0;
return 0;
}
B.小杜捕鱼
离一个点曼哈顿距离最远的点一定在四个角上,因此算出四个角需要的距离,在取最小值即可。
#include <bits/stdc++.h>
#define int long long
using namespace std;
int32_t main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n , m , res = 0;
cin >> n >> m;
vector<pair<int,int>> v;
for( int i = 1 ; i <= n ; i ++ ){
string s;
cin >> s;
for( int j = 1 ; j <= m ; j ++ )
if( s[j-1] == '#' ) v.push_back(make_pair(i,j));
}
vector<pair<int,int>> a;
a.push_back(make_pair(1,1));
a.push_back(make_pair(1,m));
a.push_back(make_pair(n,1));
a.push_back(make_pair(n,m));
auto dis = []( pair<int,int> a , pair<int,int> b ){
return abs( a.first - b.first ) + abs( a.second - b.second );
};
for( auto i : a ){
int ans = 0;
for( auto j : v )
ans = max( ans , dis(i,j) );
res = max( res , ans );
}
cout << res << "\n";
return 0;
}
C.Karashi的生日蛋糕
首先把每一圈的水果先给每个人分\(\frac i k\),这样还剩下\(i%k\)个,记录下来。之后对\(k\)个人按照已经有的水果总数排序,优先给水果少的,并且保证每次加一
#include <bits/stdc++.h>
#define int long long
using namespace std;
int32_t main(){
ios::sync_with_stdio(false) , cin.tie(nullptr);
int n , k ;
cin >> n >> k;
vector<vector<int>> res( k , vector<int>( n+1 , 0 ) );
for( int t , i = 1 ; i <= n ; i ++ ){
t = i / k;
for( int j = 0 ; j < k ; j ++ ) res[j][i] = t , res[j][0] += t;
}
for( int i = 1 ; i <= n ; i ++ ){
if( i % k == 0) continue;
sort( res.begin() , res.end() , []( const vector<int> & a , const vector<int> & b ){
return a[0] < b[0];
});
for( int j = 0 ; j < i % k ; j ++ )
res[j][i] ++ , res[j][0] ++;
}
for( int i = 0 ; i < k ; i ++ )
for( int j = 1 ; j <= n ; j ++ )
cout << res[i][j] << " \n"[j==n];
return 0;
}
D.Karashi的树 I
其实任意一个点都可以换到任意位置上去,所以我们把点权排序,再把点按照子树大小排序,然后一一对应就是最优解。
#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;
}
int n , res;
vector<int> a , val, si;
vector<pair<int,int>> cur;
vector<vector<int>> e;
void dfs( int x ){
si[x] = 1;
for( auto v : e[x] ){
dfs( v ) , si[x] += si[v];
}
cur.push_back(make_pair( si[x] , x ) );
return;
}
void dfs( int x , int sum ){
sum += val[x] , res += sum;
for( auto v : e[x] ){
dfs( v , sum );
}
return;
}
int32_t main(){
n = read();
val = si = a = vector<int>(n);
e = vector<vector<int>>( n , vector<int>() );
for( auto & i : a ) i = read();
for( int fa , i = 1 ; i < n ; i ++ )
fa = read() - 1 , e[fa].push_back(i);
dfs( 0 );
sort( cur.begin() , cur.end() );
sort( a.begin() , a.end() );
for( int i = 0 ; i < n ; i ++ )
val[ cur[i].second ] = a[i];
dfs( 0 , 0 );
cout << res << "\n";
return 0;
}
E.Karashi的数组 I
令\(A=a[k] , B=\sum_{k+1}^{k+len} a[k] , C = a[k+len+1]\),则题目所给条件为\((A+B)\times(B+C)=(A+B+C)\times B\)
化简可得\(AC=0\)所以题目求的是\(k\in[1,n-len-1]\)中满足\(a[k]\times a[k+len+1]=0\)的个数
其实我们修改一点只会至多影响两个k是否成立,所以这道题\(O(n)\)的过一遍,一边修改一遍判断就好。
#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 m , n , len , cnt = 0;
vector<int> a;
void update( int p , int v ){
if( p-len-1 >= 0 && a[p]*a[p-len-1] == 0 ) cnt--;
if( p+len+1 < n && a[p]*a[p+len+1] == 0 ) cnt --;
a[p] = v;
if( p-len-1 >= 0 && a[p]*a[p-len-1] == 0 ) cnt++;
if( p+len+1 < n && a[p]*a[p+len+1] == 0 ) cnt ++;
}
int32_t main(){
n = read() , m = read() , len = read() , a.resize(n);
for( auto & i : a ) i = read();
for( int i = 0 ; i < n - len - 1 ; i ++ )
if( a[i] * a[i+len+1] == 0 ) cnt ++;
for( int p , v ; m ; m -- ){
p = read() - 1 , v = read();
update( p , v );
cout << cnt << "\n";
}
return 0;
}