因为是渡劫场,所以来水一篇题解(手速场,运气好,快速过了(a~e))
A
略
代码
void solve () {
ll n ; cin >> n ;
vector < ll > a( n ) ;
for ( int i = 0 ; i < n ; i += 1 ) {
cin >> a [ i ] ;
}
ll ans = 0 , res = 0, cnt = 0 ; bool flag = 0 ;
for ( int i = 0 ; i < n ; i += 1 ) {
if ( !flag && a [ i ] == 1 ) {
flag = 1 ;
}
if ( !flag ) continue ;
if ( a [ i ] == 0 ) res += 1 ;
else ans += res , res = 0 ;
}
cout << ans << endl ;
}
B
略
代码
void solve () {
ll n , k ; cin >> n >> k ;
vector < ll > a ( n ) , x ( n ) ;
for ( int i = 0 ; i < n ; i += 1 ) {
cin >> a [ i ] ;
}
std::map < ll , ll > map ;
for ( int i = 0 ; i < n ; i += 1 ) {
cin >> x [ i ] ;
map [ abs ( x [ i ] ) ] += a [ i ] ;
}
// vector < array < ll , 2 > > v ( map.begin () , map.end () ) ;
ll ans = 0 , now = 0 , res = 0 ;
for ( auto [ x , val ] : map ) {
res += ( x - now ) * k ;
now = x ;
res -= val ;
if ( res < 0 ) {
cout << "NO" << endl ;
return ;
}
}
cout << "YES" << endl ;
}
C
可以证明,把 a a a 对应 1 1 1 的位置在 b b b 中对应 2 2 2 , a a a 大于 1 1 1 的数对应 b b b 中的 1 1 1 就行。如果对应区间长度为 1 1 1 ,显然无解,对应 b b b 对应区间小于等于 a a a 对应区间,显然有解
代码
void solve () {
ll n , q ; cin >> n >> q ;
vector < ll > a ( n ) ;
for ( int i = 0 ; i < n ; i += 1 ) {
cin >> a [ i ] ;
}
vector < ll > b ( n ) ;
for ( int i = 0 ; i < n ; i += 1 ) {
if ( a [ i ] == 1 ) b [ i ] = 2 ;
else b [ i ] = 1 ;
}
vector < ll > sum1 ( n ) ;
vector < ll > sum2 ( n ) ;
sum1 [ 0 ] = a [ 0 ] , sum2 [ 0 ] = b [ 0 ] ;
for ( int i = 1 ; i < n ; i += 1 ) {
sum1 [ i ] = sum1 [ i - 1 ] + a [ i ] ;
sum2 [ i ] = sum2 [ i - 1 ] + b [ i ] ;
}
while ( q-- ) {
ll l , r ; cin >> l >> r ; -- l , -- r ;
if ( l == r ) {
cout << "NO" << endl ;
continue ;
}
if ( sum2 [ r ] - ( l == 0 ? 0 : sum2 [ l - 1 ] ) <= sum1 [ r ] - ( l == 0 ? 0 : sum1 [ l - 1 ] ) ) {
cout << "YES" << endl ;
}
else cout << "NO" << endl ;
}
}
D
赛上卡了几分钟,就是假如对应 a a a 的一个位置,假如你小于左边或右边,显然为 1 1 1 ,大于左边(右边同理)时,你需要当前位置 i i i 从左边第一个数开始往左的找到第一个点 j j j ,使得 ∑ i t = j i − 1 a [ i t ] > a [ i ] \sum_{it=j}^{i-1} a [it]>a[i] ∑it=ji−1a[it]>a[i](先往下看),但是注意到假如你左边连续相等的话是不能相互吞并的,所以你需要维护一个第一个不与左边相等的数的位置的数组,这很简单,然后维护一下前缀和二分一下就能找到答案
void solve () {
ll n ; cin >> n ;
vector < ll > a ( n ) ;
for ( int i = 0 ; i < n ; i += 1 ) {
cin >> a [ i ] ;
}
vector < ll > l ( n ) , r ( n ) , lf ( n ) , rf ( n ) ;
for ( int i = 0 ; i < n ; i += 1 ) {
r [ i ] = ( i == 0 ? 0 : r [ i - 1 ] ) + a [ i ] ;
if ( i == 0 ) lf [ i ] = -1 ;
else lf [ i ] = ( a [ i ] == a [ i - 1 ] ? lf [ i - 1 ] : i - 1 ) ;
}
for ( int i = n - 1 ; i >= 0 ; i -= 1 ) {
l [ i ] = ( i == n - 1 ? 0 : l [ i + 1 ] ) + a [ i ] ;
if ( i == n - 1 ) rf [ i ] = n ;
else rf [ i ] = ( a [ i ] == a [ i + 1 ] ? rf [ i + 1 ] : i + 1 ) ;
}
vector < ll > ans ( n , -1 ) ;
for ( int i = 0 ; i < n ; i += 1 ) {
if ( ( i != 0 && a [ i ] < a [ i - 1 ] ) || ( i != n - 1 && a [ i ] < a [ i + 1 ] ) ) {
ans [ i ] = 1 ; continue ;
}
ll fa = ( i == 0 ? -1 : lf [ i - 1 ] ) ;
auto it = upper_bound ( l.rbegin () + ( n - 1 ) - fa , l.rend () , l [ i ] + a [ i ] ) ;
if ( it != l.rend () ) {
if ( ans [ i ] == -1 ) {
ans [ i ] = i - ( ( n - 1 ) - ( it - l.rbegin () ) ) ;
}
}
fa = ( i == n - 1 ? n : rf [ i + 1 ] ) ;
auto it2 = upper_bound ( r.begin () + fa , r.end () , r [ i ] + a [ i ] ) ;
if ( it2 != r.end () ) {
if ( ans [ i ] == -1 ) {
ans [ i ] = it2 - r.begin () - i ;
}
else ans [ i ] = std::min ( ans [ i ] , it2 - r.begin () - i ) ;
}
}
for ( int i = 0 ; i < n ; i += 1 ) {
cout << ans [ i ] << ' ' ;
}
cout << endl ;
}
E
几乎和前几天abc压轴G题一模一样
树上启发式合并,非常经典
看完之后看看我代码就行了
void solve () {
ll n ; cin >> n ;
vector < ll > a ( n ) ;
for ( int i = 0 ; i < n ; i += 1 ) {
cin >> a [ i ] ;
}
vector < vector < ll > > map ( n ) ;
for ( int i = 1 ; i < n ; i += 1 ) {
ll u , v ; cin >> u >> v ; -- u , -- v ;
map [ u ].push_back ( v ) ;
map [ v ].push_back ( u ) ;
}
ll ans = 0 ;
auto dfs = [ & ] ( auto&& dfs , ll now , ll fa ) -> std::map < ll , ll > {
std::map < ll , ll > f ;
for ( auto here : map [ now ] ) {
if ( here == fa ) continue ;
std::map < ll, ll > s = move ( dfs ( dfs , here , now ) ) ;
ans += s [ a [ now ] ] ;
s [ a [ now ] ] = 0 ;
if ( s.size () > f.size () ) swap ( f , s ) ;
for ( auto [ x , sz ] : s ) {
auto& fsz = f [ x ] ;
ans += fsz * sz ;
fsz += sz ;
}
}
f [ a [ now ] ] = 1 ;
return f ;
};
dfs ( dfs , 0 , 0 ) ;
cout << ans << endl ;
}
区间操作与树上合并问题的代码分析
540

被折叠的 条评论
为什么被折叠?



