生活随笔
收集整理的這篇文章主要介紹了
codeforce训练2总结
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目列表 A.most unstable array 題號 題意 n個非負正數和為m,求所有相鄰兩數絕對值之和,即 分析 選擇其中一個數為m本身,其他都取0。 為便于分析,分為兩種情況來看。 如果n為奇數,取法有很多種。 只需要排列的開頭和結尾都是0,并且非零數以0為間隔,這樣的差的絕對值最大。每個非零數aia_i a i ? 與其兩邊的零相差絕對值為2*aia_i a i ? ,然后進行累加,結果就是2m。舉例,5個數和為7,則可以取[0,3,0,4,0],相鄰兩數差的絕對值之和為3+3+4+4=14=27=2m;或者取[0,1,0,6,0],相鄰兩數差的絕對值之和為1+1+6+6=14=27=2m,或者取[0,7,0,0,0]=7+7=14=2m 當然這是奇數的情況。 如果n為偶數,只能[0,m,0,0,…]這樣來做。
綜上,最簡單的做法如下: n= =1時,排列為[m]結果為0 n==2時,排列為[m,0]結果為m n>=3時,排列為[0,m,0,0,0](其中n-1個0),結果為2m
ac代碼
#include <iostream> using namespace std
; int t
;
long long n
, m
;
int main ( ) { cin
>> t
; while ( t
-- ) { cin
>> n
>> m
; if ( n
== 1 ) { cout
<< 0 << endl
; continue ; } if ( n
== 2 ) { cout
<< m
<< endl
; continue ; } cout
<< m
* 2 << endl
; }
}
B.Two Arrays And Swaps 題號280477B - 12 題意 給定兩個等長的序列a和b,允許兩個序列交換數字,但是給定交換次數的最大值k。要求在不超過k次交換使得a序列元素之和變得最大
分析 a從小到大排序,b從大到小排序,b中最大的與a中最小的交換。 當然需要分情況討論 【1】交換次數==0,直接輸出sum 【2】a所有數字都比b中的大,不需要交換,直接輸出sum 【3】a中所有數字都比b中的小,那么交換k次。 【4】b中部分數字比a中部分數字大,兩個指針來比較
int p1
= 0 , p2
= 0 ; while ( p1
!= n
&& p2
!= n
&& k
!= 0 ) { if ( b
[ p2
] > a
[ p1
] ) { sum
+ = b
[ p2
] - a
[ p1
] ; k
-- ; p2
++ ; } p1
++ ; }
ac代碼 ac代碼鏈接代碼和原題
#include <iostream>
#include <algorithm>
using namespace std
;
const int maxn
= 40 ;
int t
, n
, k
, a
[ maxn
] , b
[ maxn
] ;
int main ( ) { cin
>> t
; while ( t
-- ) { cin
>> n
>> k
; long long sum
= 0 ; for ( int i
= 0 ; i
< n
; i
++ ) { cin
>> a
[ i
] ; sum
+ = a
[ i
] ; } for ( int i
= 0 ; i
< n
; i
++ ) { cin
>> b
[ i
] ; } if ( k
== 0 ) { cout
<< sum
<< endl
; continue ; } sort ( a
, a
+ n
) ; sort ( b
, b
+ n
, greater
< int > ( ) ) ; if ( b
[ 0 ] <= a
[ 0 ] ) { cout
<< sum
<< endl
; continue ; } else if ( b
[ n
- 1 ] >= a
[ n
- 1 ] ) { for ( int i
= 0 ; i
< k
; i
++ ) { sum
+ = b
[ i
] - a
[ i
] ; } } else { int p1
= 0 , p2
= 0 ; while ( p1
!= n
&& p2
!= n
&& k
!= 0 ) { if ( b
[ p2
] > a
[ p1
] ) { sum
+ = b
[ p2
] - a
[ p1
] ; k
-- ; p2
++ ; } p1
++ ; } } cout
<< sum
<< endl
; sum
= 0 ; } return 0 ;
}
D. 需要采用優先隊列,每次按照區間長度排序,區間長度相同則做左端點小的優先級高。
bfs+二分賦值即可 bfs模板中的隊列改為優先隊列priority_queue,每次取出長度最大的連續為0的區間,然后取中點賦值,如果長度相等,則取區間左端點靠前的區間來取中點賦值。
#include <iostream>
#include <queue>
#include <cstring> using namespace std
;
const int maxn
= 2e5 + 10 ; int t
, n
, a
[ maxn
] ; struct seg
{ int l
; int r
; int len
; bool operator < ( const seg
& s2
) const { if ( s2
. len
== len
) return l
> s2
. l
; else return len
< s2
. len
; }
} ; seg start
, tmp
, tmp2
; int main ( ) { cin
>> t
; while ( t
-- ) { priority_queue
< seg
> pq
; memset ( a
, 0 , sizeof ( a
) ) ; cin
>> n
; start
. l
= 1 ; start
. r
= n
; start
. len
= n
; pq
. push ( start
) ; int cnt
= 0 ; while ( ! pq
. empty ( ) ) { tmp
= pq
. top ( ) ; pq
. pop ( ) ; cnt
++ ; int mid
= ( tmp
. l
+ tmp
. r
) / 2 ; if ( a
[ mid
] == 0 ) { a
[ mid
] = cnt
; } if ( tmp
. l
<= mid
- 1 ) { tmp2
. l
= tmp
. l
; tmp2
. r
= mid
- 1 ; tmp2
. len
= tmp2
. r
- tmp2
. l
+ 1 ; pq
. push ( tmp2
) ; } if ( mid
+ 1 <= tmp
. r
) { tmp2
. l
= mid
+ 1 ; tmp2
. r
= tmp
. r
; tmp2
. len
= tmp2
. r
- tmp2
. l
+ 1 ; pq
. push ( tmp2
) ; } } for ( int i
= 1 ; i
<= n
; i
++ ) { cout
<< a
[ i
] << " " ; } cout
<< endl
; } }
總結
以上是生活随笔 為你收集整理的codeforce训练2总结 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。