女神训练赛 Round 02
棋盘问题
这题就是简单的搜索,类似八皇后问题,dfs 枚举每一行放在哪里一列,或者不放。在枚举的过程中直接筛掉之前放过的列。
#include <string>
#include <iostream>
using namespace std;
int n , m , res;
bool v[15];
string g[15];
void dfs( int x , int t ){
if( t == m ) {
res++;
return;
}
if( x == n ) return;
dfs( x + 1 , t );
for( int i = 0 ; i < n ; i ++ ){
if( v[i] || g[x][i] == '.' ) continue;
v[i] = 1 , dfs( x + 1 , t + 1 ) , v[i] = 0;
}
return;
}
void solve(){
for( int i = 0 ; i < n ; i ++ ) cin >> g[i];
fill( v , v + 15 , false );
res = 0;
dfs( 0 , 0 );
cout << res << "\n";
}
int32_t main() {
while(1){
cin >> n >> m;
if( n == m && n == -1 ) return 0;
solve();
}
}
Black Box
这套题的解法很多,这里讲一个我期望的做法,就是对顶堆。
我分别维护一个大根堆和一个小根堆。
比如这次的GET
操作要求的是i
,那么我就要保证大根堆中有i-1
个数,且是最小的i-1
个数,剩余的数都在小跟堆中。因为最小的i-1
个数都在大根堆中,此时小根堆的堆顶就是第i
小的数。
当每次i=i+1
的时候我都把小根堆的堆顶移动到大根堆中,这样在下一次询问的时候答案依旧是小根堆的堆顶。
那么问题来了,小根堆很好理解,为了每次取出剩下的数中最小的一个。为什么是大根堆呢?
在ADD
操作的时候,如果x
是大于第i-1
小的数,显然直接插入到小根堆中就好了。但是如果x
小于第i-1
小的数,如果插入到小根堆中,就无法满足大根堆中是最小的i-1
个数的性质了,所以此时前i-1
小的数中最大的数放入到小跟堆中,在把x
插入到大根堆中,才能满足大根堆中是最小的i-1
个数。
上述的操作看起来很麻烦,其实是可以合并操作的,在ADD
的时候,先把x
插入到大根堆中,在把大根堆的堆顶移动到小根堆中就好。不明白为什么这样合并的自己模一下简单数据就懂了。
所以这样的话,每次插入和询问的操作复杂度都是\(O(\log n)\)的,整体的复杂度就是O(n\log n)
的
#include <iostream>
#include <queue>
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 = 30005;
int a[N] , b[N];
priority_queue<int> l;// 大根堆
priority_queue<int , vector<int> , greater<int> > r;// 小根堆
int32_t main(){
int n = read() , m = read() ;
for( int i = 1 ; i <= n ; i ++ )
a[i] = read();
// i 第i次 GET 操作 , j表示时间,在 j 时间应该 ADD( a[j] )
for( int i = 1 , j = 1 , x ; i <= m ; i ++ ){
x = read();
for( ; j <= x ; j ++ )
l.push( a[j] ) , r.push( l.top() ) , l.pop();
cout << r.top() << "\n";
l.push( r.top() ) , r.pop();
}
}
∵∴∵
这道其实算是签到题了,把两个字符串按照奇偶位置合并就好了
#include<bits/stdc++.h>
using namespace std;
int32_t main() {
string a , b;
cin >> a >> b;
for( int i = 0 ; i < a.size() ; i ++ ){
cout << a[i];
if( i < b.size() ) cout << b[i];
}
return 0;
}