2023寒假训练Week0
Day 1
Day 2
One Bamboo Contest Round #11(Clone from 2022 ICPC Manila)
Day 3
CF580C
一棵以1为根的树,树上有些点是红的。一个叶子是合法的当且仅当从根到它的路径上出现的连续红点个数不超过m。求有多少个叶子是合法的。
其实这种题,感觉起手一个dfs就能秒,但是学弟让帮忙看就硬着头皮用bfs写了一下。
continuous 表示连续的个数 , val 表示路径上最长连续个数 , leaf 表示是否是叶子。
#include <bits/stdc++.h>
using namespace std;
int read(){...}
int main(){
int n = read() , m = read();
vector<int> a(n+1) , val(n+1) , vis( n + 1 ) , leaf( n + 1 , 1 ) , continuous(n+1);
for( int i = 1 ; i <= n ; i ++ ) a[i] = read();
vector e( n+1 , vector<int>() );
for( int i = 1 , u , v ; i < n ; i ++ )
u = read() , v = read() , e[u].push_back(v) , e[v].push_back(u);
queue<int> q;
q.push(1);
vis[1] = 1 , continuous[1] = val[1] = a[1];
while( q.size() ){
int u = q.front(); q.pop();
vis[u] = 1;
for( auto v : e[u] ){
if( vis[v] ) continue;
leaf[u] = 0;
if( a[v] ) continuous[v] = continuous[u] + 1;
val[v] = max( val[u] , continuous[v] );
q.push(v);
}
}
int res = 0;
for( int i = 1 ; i <= n ; i ++ )
res += ( leaf[i] && val[i] <= m );
cout << res << "\n";
}
One Bamboo Contest Round #12(Clone from 2020 ICPC Shenyang)
Day 4
AcWing 4261. 孤独的照片
这题其实难点在于统计左右两侧连续不同的个数,用两个变量记录一下就好
#include <bits/stdc++.h>
#define int long long
using namespace std;
int32_t main(){
string s;
int n , res = 0;
cin >> n >> s;
vector<int> l(n+1) , r(n+1);
for( int i = 1 , g = 0 , h = 0 ; i <= n ; i ++ ){
if( s[i-1] == 'G' ) l[i] = h , h = 0 , g ++;
else l[i] = g , g = 0 , h ++;
}
for( int i = n , g = 0 , h = 0 ; i >= 1 ; i -- ){
if( s[i-1] == 'G' ) r[i] = h , h = 0 , g ++;
else r[i] = g , g = 0 , h ++;
}
for( int i = 1 ; i <= n ; i ++ )
res += (l[i]*r[i]) + max( l[i]-1 , 0ll ) + max( r[i]-1 , 0ll );
cout << res << "\n";
return 0;
}
AcWing 3400. 统计次数
数据范围太小直接暴力做就行
#include <bits/stdc++.h>
#define int long long
using namespace std;
int32_t main(){
string s;
int n , k , res = 0;
cin >> n >> k;
auto f = [k]( int x ){
int cnt = 0;
while( x ) cnt += ( k == x % 10 ) , x /= 10;
return cnt;
};
for( int i = 1 ; i <= n ; i ++ ) res += f(i);
cout << res << "\n";
return 0;
}
AcWing 4366. 上课睡觉
操作\(x\)次则剩下\(n-x\)堆,且每堆\(y=\frac{\sum a_i}{n-x}\),可知要让\(x\)尽可能小则\(y\)尽可能小,这样枚举\(y\)然后判断是否可以划分成每一堆都是\(y\)即可,复杂度\(O(n\sum a_i)\),实际上是很难跑满的,稍微加几个剪枝就能跑的飞快
#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() , sum = 0 , maxVal = INT_MIN;
vector<int> a(n);
for( auto & i : a )
i = read() , sum += i , maxVal = max( maxVal , i );
if( maxVal == 0 ){
cout << "0\n";
return;
}
auto check = [a]( int x ){
int cnt = 0;
for( auto i : a ){
cnt += i;
if( cnt > x ) return false;
if( cnt == x ) cnt = 0;
}
return true;
};
for( int i = maxVal ; i <= sum ; i ++ ){
if( sum % i ) continue;
if( check(i) == false ) continue;
cout << n - sum / i << "\n";
return;
}
}
int main(){
for( int t = read() ; t ; t -- )
solve();
}
AcWing 3443. 学分绩点
#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(){
auto f = []( int x ){
if( x < 60 ) return 0.0;
if( x <= 63 ) return 1.0;
if( x <= 67 ) return 1.5;
if( x <= 71 ) return 2.0;
if( x <= 74 ) return 2.3;
if( x <= 77 ) return 2.7;
if( x <= 81 ) return 3.0;
if( x <= 84 ) return 3.3;
if( x <= 89 ) return 3.7;
return 4.0;
};
int n;
cin >> n;
vector<double> w(n);
double sum = 0 , res = 0;
for( auto &i : w ) cin >> i , sum += i;
for( auto i : w ){
int x; cin >> x;
res += i * f(x);
}
cout << fixed << setprecision(2) << res / sum;
}
AcWing 4818. 奶牛大学
排个序就行
#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;
}
int32_t main(){
int n = read();
vector<int> w(n);
for( auto & i : w ) i = read();
std::sort(w.begin(), w.end(),greater<int>());
int res = 0 , t = 0 , cnt = 0 , sum ;
for( auto i : w ){
sum = i * ( ++ t );
if( sum >= res ) res = sum , cnt = i;
}
cout << res << " " << cnt;
}
Day 5
牛客小白月赛64
Good Bye 2022: 2023 is NEAR
Day 6
AcWing 4645. 选数异或
用哈希表维护hs[i]
动态的维护数字i
最后出现的位置,f[i]
表示以\(i\)为右端点,左端点最靠右且可以满足区间内有两个数的异或值为\(x\)
则状态转移方程为f[i] = max( f[i-1] , hs[ a[i] ^ x ] )
,代码种变量名与题目不完全一致。
#include<bits/stdc++.h>
#define int long long
using namespace std;
int read(){...}
int32_t main(){
int n = read() , m = read() , k = read();
unordered_map<int,int> hs;
vector<int> f(n+1) ;
for( int i = 1 , x ; i <= n ; i ++ ){
x = read();
f[i] = max( f[i-1] , hs[x^k] );
hs[x] = i;
}
for( int l , r ; m ; m -- ){
l = read() , r = read();
if( l <= f[r] ) printf("yes\n");
else printf("no\n");
}
return 0;
}