Codeforces Round #835 (Div. 4)
A. Medium Number
#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;
}
void solve(){
vector<int>v(3);
for( int & i : v)
i = read();
std::sort(v.begin(), v.end());
cout << v[1] << "\n";
}
int main(){
for( int t = read(); t ; t -- )
solve();
}
B. Atilla's Favorite Problem
#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;
}
void solve(){
int n = read();
string s;
cin >> s;
int res = 0;
for( auto i : s )
res = max( res , i - 'a' + 1 );
cout << res << "\n";
}
int main(){
for( int t = read(); t ; t -- )
solve();
}
C. Advantage
赛时我的做法是求区间最值,所以自然而然的想到了ST
表
#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;
}
const int N = 2e5+5 , logN = 20;
int n , a[N] , log_2[N];
int f[N][logN + 5];
int getMax( int l , int r ){
if( r < l ) return INT_MIN;
int s = log_2[ r - l + 1 ];
return max( f[l][s] , f[ r - (1<<s) + 1 ][s] );
}
void solve(){
n = read();
for( int i = 1 ; i <= n ; i ++ ) a[i] = read();
log_2[0] = -1;
for( int i = 1 ; i <= n ; i ++ )
f[i][0] = a[i] , log_2[i] = log_2[i>>1] + 1;
for( int j = 1 ; j <= logN ; j ++ )
for( int i =1 ; i + ( 1 << j ) - 1 <= n ; i ++ )
f[i][j] = max( f[i][j-1] , f[ i+(1<<j-1) ][j-1] );
for( int i = 1 ; i <= n ; i ++ )
printf("%d " , a[i] - max(getMax( 1 , i-1 ) , getMax( i+1 , n ) ) );
printf("\n");
return;
}
int main(){
for( int t = read(); t ; t -- )
solve();
}
然后发现只要求一下最大值和次大值即可
#include<bits/stdc++.h>
#define int long long
using namespace std;
int read() {...}
void solve(){
int n = read() , a = INT_MIN , b = INT_MIN;
vector<int> v(n);
for( auto &i : v ) i = read();
for( auto i : v ) {
if( i >= a ) b = a , a = i;
else if( i > b ) b = i;
}
for( auto i : v ){
if( i == a ) printf("%lld " , i-b );
else printf("%lld " , i - a );
}
printf("\n");
return;
}
int32_t main() {
for( int t = read() ; t ; t -- )
solve();
return 0;
}
D. Challenging Valleys
为了方便计算,在开头和结尾分别加上两个无穷大,然后\(O(n)\)的找一下谷的个数就好
#include<bits/stdc++.h>
using namespace std;
int read(){...}
void solve(){
int n = read() , flag = 0;
vector<int> v;
v.push_back(INT_MAX);
for( int i = 1 , x ; i <= n ; i ++ ) x = read() , v.push_back(x);
v.push_back(INT_MAX);
for( int l = 1 , r ; l <= n; l ++ ){
if( v[l-1] <= v[l] ) continue;
for( r = l ; v[r]== v[l] && r <= n ; r ++ );
r --;
if( v[r] < v[r+1] ) flag ++;
l = r;
}
printf( (flag == 1 ? "YES\n" : "NO\n") );
return;
}
int main(){
for( int t = read(); t ; t -- )
solve();
}
E. Binary Inversions
首先可以倒序枚举统计一下再不进行任何操作时逆序对的数量
然后枚举操作哪一位就好了,枚举前先对序列求一下前缀和记为\(b_i\)
如果这一位是1
,删后0
也就是-( (n - i) - (b[n] - b[i]) )
,加前1
也就是+b[i-1]
化简得-n+i+b[n]-1
如果这一位是0
,删前1
也就是-b[i-1]
,加后0
,也就是+( (n-i) - (b[n]-b[i]) )
化简得n-i-b[n]
通过化简我们发现其实不用前缀和只需要知道一共有多少1
即可
#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;
}
const int N = 2e5+5;
int a[N] , b[N];
void solve(){
int n = read() , cnt = 0, res = 0 , ans;
for( int i = 1 ; i <= n ; i ++ ) a[i] = read() , b[i] = b[i-1] + a[i];
for( int i = n ; i >= 1 ; i -- ){
if( a[i] == 0 ) cnt ++;
else res += cnt;
}
cnt = n - cnt;
ans = res;
for( int i = 1 ; i <= n ; i ++ ){
if( a[i] == 0 )
ans = max( ans , res + n - i - cnt );
else
ans = max( ans , res - n + i + cnt - 1 );
}
cout << ans << "\n";
}
int32_t main(){
for( int t = read(); t ; t -- )
solve();
}
F. Quests
因为要尽可能的多选,所以要尽可能的选当前能选的最大值,所以把序列排一个序,然后求前缀和。
然后二分一下最大的k
就好,并且把二分的上届设为大于d 的值,这样如果二分的结果是大于等于d
的话,答案就是Infinity
#include<bits/stdc++.h>
#define int long long
using namespace std;
int read(){...}
const int N = 2e5+50;
int a[N] , f[N] , n , c , d , sum;
bool check( int k ){
k ++;
int tt = a[k] * ( d / k ) + a[ d % k ];
return tt >= c;
}
void solve(){
n = read() , c = read() , d = read() , sum;
memset( a , 0 , sizeof(a) );
for( int i = 1 ; i <= n ; i ++ ) a[i] = read();
sort( a+1 , a+1+n , greater<int>() );
for( int i = 1 ; i <= max( d , n )+10 ; i ++ ) a[i] += a[i-1];
int l = 0 , r = d+10, res = -1;
while( l <= r ){
int mid = ( l + r ) >> 1;
if( check( mid ) ) res = mid , l = mid + 1;
else r = mid - 1;
}
if( res == -1 ) printf("Impossible\n");
else if( res >= d ) printf("Infinity\n");
else printf("%lld\n" , res );
}
int32_t main(){
for( int t = read(); t ; t -- )
solve();
}
G. SlavicG's Favorite Problem
这题其实就是先求出从a
出发到所有点的异或和,在求出从b
出发到所有点的异或和,然后判断是否有相同的异或和就好。
所以很自然想到用 set 来存a
到所有点的异或和,然后在从b
进行 dfs 的时候判断即可。
注意的坑点从b
出发的点判断是否在 set 中的时候要b
本身特判掉,并且从 a
出发如果到达b
则不能继续搜索下去了,并且如果异或和为0
就要直接结束,因为可以不进行任何一跳。
#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;
}
const int N = 1e5+5;
typedef pair<int,int> PII;
int a , b , n , flag;
bool vis[N];
set<int> all;
vector<PII> e[N];
void dfs( int u , int val){
vis[u] = true;
if( u != b ) all.insert( val );
else {
if( val == 0 ) flag = 1;
return;
}
for( auto [ v , w ] : e[u] ){
if( vis[v] ) continue;
dfs( v , val ^ w );
}
return;
}
bool Dfs( int u , int val ){
vis[u] = true;
if( u != b && all.count( val ) ) {
return true;
}
for( auto [ v , w ] : e[u] ){
if( vis[v] ) continue;
if( Dfs( v , val ^ w ) ) return true;
}
return false;
}
void solve(){
n = read() , a = read() , b = read() , flag = 0;
fill( e+1 , e+1+n , vector<PII> () );
fill( vis+1 , vis+1+n , false );
for( int i = 1 , u , v , w ; i < n ; i ++ )
u = read() , v = read() , w = read() ,
e[u].emplace_back( v , w ) , e[v].emplace_back( u , w );
all.clear();
dfs( a , 0 );
if( flag ){
printf("YES\n");
return;
}
fill( vis+1 , vis+1+n , false );
printf( (Dfs( b ,0 ) == true ? "YES\n" : "NO\n") );
}
int32_t main(){
for( int t = read(); t ; t -- )
solve();
}