BUCOJ周赛5题解
A
签到题
#include <bits/stdc++.h>
using namespace std;
int a , b ;
int main()
{
cin >> a >> b;
if( a < b ) puts("0");
else puts("10");
}
B
枚举即可,判断特殊情况恰好跳到x
和根本跳不到x
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n , m ;
cin >> n >> m;
int ans = 0;
for( int i = 1 , x ; i <= n ; i ++ )
{
cin >> x;
ans += x;
if( ans < m ) continue;
else if( ans == m ) cout << i + 1 << endl;
else cout << i << endl;
return 0;
}
cout << n + 1 << endl;
}
C
多画几次就会发现一定可以分成一半一半
如果(x,y)
在两条对角线的焦点上有无数种情况,反之只有(x,y)
与对角线交点连线这一种情况
#include <bits/stdc++.h>;
using namespace std;
double n , m , a , b;
int main()
{
cin >> n >> m >> a >> b;
printf("%.6lf " , n * m / 2 );
if( a == n / 2 && b == m / 2 ) cout << 1 << endl;
else cout << 0 << endl;
}
D
二分 前缀和
如果[l,r]
满足,则[l,r+1]
也满足一直到[l,n]
全部都满足
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e5 + 5;
int n ;
ll a[N] , cnt , k ;
inline ll read()
{
ll x = 0;
char ch = getchar();
while( ch < '0' || ch > '9' ) ch = getchar();
while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar();
return x;
}
int main()
{
n = read() , k = read();
for( int i = 1 ; i <= n ; i ++ ) a[i] = a[ i - 1 ] + read();
for( int i = 1 , x ; i <= n ; i ++ )
{
if( a[n] - a[ i - 1 ] < k ) break;
cnt += n - ( lower_bound( a + 1 , a + 1 + n , a[ i - 1 ] + k ) - a ) + 1;
}
cout << cnt << endl;
return 0;
}
E
动态规划
设f[i][j]
为S到i,T到j有多少个公共子串若s[i]==t[i]
,i-1
、j-1
任意一个子串都可以
f[i][j] =f[i-1][j-1] + f[i-1][j]+f[i][j-1]-f[i-1][j-1]+1
若不相等,则是s[i]
和t[j]
不能同时选
f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1]
#include <bits/stdc++.h>
using namespace std;
const int N = 2e3 + 50 , Mod = 1e9 + 7;
int n , m , a[N] , b[N] ;
long long f[N][N];
signed main()
{
cin >> n >> m;
for( int i = 1 ; i <= n ; i ++ ) cin >> a[i];
for( int i = 1 ; i <= m ; i ++ ) cin >> b[i];
for( int i = 1 ; i <= n ; i ++ )
{
for( int j = 1 ; j <= m ; j ++ )
{
if( a[i] == b[j] ) f[i][j] = f[ i - 1 ][j] + f[i][ j - 1 ] + 1;
else f[i][j] = f[ i - 1 ][j] + f[i][ j - 1 ] - f[ i - 1 ][ j - 1 ];
f[i][j] %= Mod;
}
}
cout << ( f[n][m] + 1 + Mod ) % Mod << endl;
return 0;
}
F
时间限制是100s,然后手掌面积是一个单峰函数,用三分法枚举即可
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5 ;
const int dx[] = { 0 , 1 , -1 , 0 , 0 } , dy[] = { 0 , 0 , 0 , 1 , -1 };
int n ;
struct node
{
double x , y;
int dir;
}a[N];
inline int read()
{
int x = 0 , f = 1;
char 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;
}
inline int getdir()
{
char c = getchar();
while( c != 'R' && c != 'L' && c != 'D' && c != 'U' ) c = getchar();
// R L D U
// 1 2 3 4
if( c == 'R' ) return 1;
if( c == 'L' ) return 2;
if( c == 'U' ) return 3;
if( c == 'D' ) return 4;
}
inline double f( double x )
{
double maxx = -1e10 , minx = 1e10 , maxy = -1e10 , miny = 1e10 , tx , ty;
for( int i = 1 ; i <= n ; i ++ )
{
tx = a[i].x + x * dx[ a[i].dir ] , ty = a[i].y + x * dy[ a[i].dir ];
maxx = max( maxx , tx ) , maxy = max( maxy ,ty ) , minx = min( minx , tx ) , miny = min( miny , ty );
}
return ( maxx - minx ) * ( maxy - miny );
}
int main()
{
n = read();
for( int i = 1 ; i <= n ; i ++ ) a[i].x = read() , a[i].y = read() , a[i].dir = getdir();
double l = 0 , r = 1e12 , ans = 1e18;
for( int i = 0 ; i < 300 ; i ++ )
{
double ml = l + ( r - l ) / 3 , mr = l + 2 * ( r - l ) / 3;
double ansl = f( ml ) , ansr = f( mr );
if( ansl > ansr ) l = ml;
else r = mr ;
ans = min( { ans , ansl , ansr } );
}
printf("%.6lf\n" , ans );
return 0;
}