CF 790 Div.4完整題解
阿新 • • 發佈:2022-05-24
A. Lucky?
給n 個長度6 的數,問前三位和後三位中0 的數量是否相同
#include <bits/stdc++.h> using namespace std; string s; int main(){ int t = read(); while( t -- ){ cin >> s; int a = 0 , b = 0; for( int i = 0 ; i < 3 ; i ++ ) a += s[i] - '0'; for( int i = 3 ; i < 6 ; i ++ ) b += s[i] - '0'; if( a == b ) printf("YES\n"); else printf("NO\n"); } return 0; }
B. Equal Candies
有 n 個盒子每個盒子裡面有\(a_i\)個糖果,可以吃掉任何一個盒子的任意數量個糖果,問最少吃掉多少糖果能使所有盒子糖果數量相同
找到糖果最少的盒子,其他盒子都變成這個數量就行
#include <bits/stdc++.h> #define ll long long using namespace std; string s; int lcm( int x , int y ){ return x * y / __gcd( x , y ) ; } 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 = 55; int a[N] , n , m ; ll sum; void solve(){ n = read() , m = 1e9 , sum = 0; for( int i = 1 ; i <= n ; i ++ ) a[i] = read() , m = min( a[i] , m ); for( int i = 1 ; i <= n ; i ++ ) sum += a[i] - m; cout << sum << endl; } int main(){ int t = read(); while( t -- ) solve(); return 0; }
C. Most Similar Words
給 n 個長度是 m 的字串,從中選出兩個兩個字串的差最小是多少
因為資料很小直接列舉一下就行,\(O(n^2m)\)
#include <bits/stdc++.h> #define ll 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 = 55; int n , m , sum , res; string s[N]; void solve(){ n = read() , m = read(); for( int i = 1 ; i <= n ; i ++ ) cin >> s[i]; res = 1e9; for( int i = 1 ; i < n ; i ++ ) for( int j = i + 1 ; j <= n ; j ++ ) { sum = 0; for( int k = 0 ; k < m ; k ++ ) sum += abs( s[i][k] - s[j][k] ); res = min( res , sum ); } cout << res << endl; } int main(){ int t = read(); while( t -- ) solve(); return 0; }
D. X-Sum
\(n^3\)解法
這個是顯然的一種做法,就是直接枚舉出每一個點,然後計算出和就好
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int lcm( int x , int y ){
return x * y / __gcd( x , y ) ;
}
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 = 500;
int n , m , sum , res;
int st[N][N];
void solve(){
n = read() , m = read();
for( int i = 1 ; i <= n ; i ++ )
for( int j = 1 ; j <= m ; j ++ )
st[i][j] = read();
res = 0;
for( int i = 1 ; i <= n ; i ++ )
for( int j = 1 ; j <= m ; j ++ )
{
sum = st[i][j];
for( int x = i-1 , y = j-1 ; x >= 1 && y >= 1 ; x -- , y -- )
sum += st[x][y];
for( int x = i-1 , y = j+1 ; x >= 1 && y <= m ; x -- , y ++ )
sum += st[x][y];
for( int x = i+1 , y = j-1 ; x <= n && y >= 1 ; x ++ , y -- )
sum += st[x][y];
for( int x = i+1 , y = j+1 ; x <= n && y <= m ; x ++ , y ++ )
sum += st[x][y];
res = max( res , sum );
}
cout << res <<'\n';
}
int main(){
int t = read();
while( t -- )
solve();
return 0;
}
\(n^2\)做法
可以首先計算出每一條斜線的和,然後再列舉一下中心點把兩條斜線加起來即可
那麼如何判斷點在哪條斜線上呢?
一條左斜的斜線距離\((1,1)\)的尤拉距離相同, 同理一條右斜的斜線距離\((n,n)\)的尤拉距離相同
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int lcm( int x , int y ){
return x * y / __gcd( x , y ) ;
}
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 = 500;
int n , m , sum , res;
int st[N][N] , lc[2*N] , rc[2*N];
void solve(){
n = read() , m = read();
memset( lc , 0 , sizeof(lc) ) , memset( rc , 0 , sizeof(rc) );
for( int i = 1 ; i <= n ; i ++ )
for( int j = 1 ; j <= m ; j ++ )
st[i][j] = read();
int l , r ;
for( int i = 1 ; i <= n ; i ++ )
for( int j = 1 ; j <= m ; j ++ )
{
l = i - 1 + j - 1 , r = n - i + j - 1;
lc[l] += st[i][j] , rc[r] += st[i][j];
}
res = 0;
for( int i = 1 ; i <= n ; i ++ )
for( int j = 1 ; j <= m ; j ++ )
{
l = i - 1 + j - 1 , r = n - i + j - 1;
sum = lc[l] + rc[r] - st[i][j];
res = max( res , sum );
}
cout << res << endl;
}
int main(){
int t = read();
while( t -- )
solve();
return 0;
}
E. Eating Queries
有 n 顆糖果,每個糖果有一個甜度\(a_i\),問需要甜度\(x\)至少要吃多少個糖果,每次詢問相互獨立
首先糖果數要少,就要優先吃甜度高的糖果。
把糖果從大到小排序,然後求一個字首和,對於每次的詢問在字首和二分查詢即可
#include <bits/stdc++.h>
#define ll long long
#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 n , a[N] , m ;
void solve(){
n = read() , m = read();
for( int i = 1 ; i <= n ; i ++ )
a[i] = read();
sort( a + 1 , a+1+n , greater<int>() );
for( int i = 1 ; i <= n ; i ++ )
a[i] += a[i-1];
for( int x , t ; m ; m -- )
{
x = read();
if( x > a[n] )
printf("-1\n");
else
{
t = lower_bound( a+1 , a+1+n , x ) - a;
printf("%lld\n" , t );
}
}
}
int32_t main(){
int t = read();
while( t -- )
solve();
return 0;
}
F. Longest Strike
給定一個序列,找出一個最長的區間,區間中的每個數都至少出現了 k 次
可以在 map 開一個桶來記錄,同時因為的 map 內部本身可以排序的,我們掃一邊就好了
注意的是,在掃的過程中我們判斷當前數是否是大於等於 k 以外還要判斷當前數是否和上一個數相鄰
#include <bits/stdc++.h>
#define ll long long
#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 n , t , l , r ;
map< int , int > st;
void solve(){
n = read() , t = read();
st.clear();
for( int i = 1 , x ; i <= n ; i ++ )
x = read() , st[x] ++;
int res = -1 , last = -1e9 , lastk = -1e9;
for( auto [k,v] : st ){
if(v >= t ){
if( last == -1e9 || lastk+1 != k ) last = k;
if( k - last > res )
res = k - last , l = last , r = k;
}
else last = -1e9;
lastk = k;
}
if( res == -1 ) printf("-1\n");
else cout << l << ' ' << r << endl;
}
int32_t main(){
int t = read();
while( t -- )
solve();
return 0;
}
G. White-Black Balanced Subtrees
給一個樹,樹上的每一個點都已一個顏色黑或者白,問有多少個點滿足子樹中的黑白點數量相同
看似複雜實際上就是直接用 dfs 過程中統計下子樹中黑白點的數量就好了
#include <bits/stdc++.h>
#define ll 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 = 4005;
int n , cnt , b[N] , w[N];
vector<int> e[N];
string s;
void dfs( int x ){
if( s[x-1] == 'B' ) b[x] ++;
else w[x] ++;
for( auto v : e[x] ){
dfs( v );
b[x] += b[v] , w[x] += w[v];
}
if( b[x] == w[x] ) cnt ++ ;
}
void solve(){
n = read() , cnt = 0;
for( int i = 1 ; i <= n ; i ++ )
e[i].clear() , b[i] = w[i] = 0;
for( int i = 2 , u ; i <= n ; i ++ )
u = read() , e[u].push_back(i);
cin >> s;
dfs( 1 );
cout << cnt << endl;
}
int32_t main(){
int t = read();
while( t -- )
solve();
return 0;
}
H. Maximum Crossings
有兩條線段,每個線段有 n 段 給定第一條線段與第二條線段連線的區間,問最多有多少個交點
這題有兩個版本,我直接寫的困難版本
其實這個題就是一個模板題,就是一個逆序對,只不過需要考慮一下邊界
#include <bits/stdc++.h>
#define ll long long
#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;
}
#define lowbit(x) ( x & -x )
const int N = 2e5+5;
int n , c[N] , cnt;
inline void update( int x ) // 更新 bit[x] += 1
{
for( int i = x ; i <= n ; i += lowbit( i ) ) c[i] += 1;
}
inline int get( int x ) //求a[1...x]
{
int ans = 0;
for( int i = x ; i ; i -= lowbit( i ) ) ans += c[i];
return ans;
}
void solve(){
n = read() , cnt = 0;
memset( c , 0 , sizeof (c) );
for( int i = 1 , x ; i <= n ; i ++ )
{
x = read();
cnt += i-1 - get(x-1);
update(x);
}
cout << cnt << endl;
}
int32_t main(){
int t = read();
while( t -- )
solve();
return 0;
}