A:Keyboard
按照题目的意思模拟即可。
#include
#include
#include
#include
using namespace std ;
typedef long long LL ;
#define rep( i , a , b ) for ( int i = a ; i < b ; ++ i )
#define For( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define rev( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i )
#define travel( e , H , u ) for ( Edge* e = H[u] ; e ; e = e -> next )
#define clr( a , x ) memset ( a , x , sizeof a )
#define cpy( a , x ) memcpy ( a , x , sizeof a )
#define ls ( o << 1 )
#define rs ( o << 1 | 1 )
#define lson ls , l , m
#define rson rs , m + 1 , r
#define root 1 , 1 , n
#define mid ( ( l + r ) >> 1 )
#define rt o , l , r
const int MAXN = 200 ;
char s[31] = "qwertyuiopasdfghjkl;zxcvbnm,./" ;
char c[5] ;
char buf[MAXN] ;
void solve () {
scanf ( "%s" , buf ) ;
if ( c[0] == 'R' ) {
for ( int i = 0 ; buf[i] ; ++ i ) {
rep ( j , 0 , 30 ) {
if ( buf[i] == s[j] ) printf ( "%c" , s[j - 1] ) ;
}
}
} else {
for ( int i = 0 ; buf[i] ; ++ i ) {
rep ( j , 0 , 30 ) {
if ( buf[i] == s[j] ) printf ( "%c" , s[j + 1] ) ;
}
}
}
printf ( "\n" ) ;
}
int main () {
while ( ~scanf ( "%s" , c ) ) solve () ;
return 0 ;
}
B:Worms
二分查找的应用。返回大于等于该数的最小值的下标。
#include
#include
#include
#include
using namespace std ;
typedef long long LL ;
#define rep( i , a , b ) for ( int i = a ; i < b ; ++ i )
#define For( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define rev( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i )
#define travel( e , H , u ) for ( Edge* e = H[u] ; e ; e = e -> next )
#define clr( a , x ) memset ( a , x , sizeof a )
#define cpy( a , x ) memcpy ( a , x , sizeof a )
#define ls ( o << 1 )
#define rs ( o << 1 | 1 )
#define lson ls , l , m
#define rson rs , m + 1 , r
#define root 1 , 1 , n
#define mid ( ( l + r ) >> 1 )
#define rt o , l , r
const int MAXN = 100005 ;
int a[MAXN] ;
int n , m ;
int search ( int x ) {
int l = 1 , r = n ;
while ( l < r ) {
int m = mid ;
if ( a[m] >= x ) r = m ;
else l = m + 1 ;
}
return l ;
}
void solve () {
int x ;
a[0] = 0 ;
For ( i , 1 , n ) scanf ( "%d" , &a[i] ) , a[i] += a[i - 1] ;
scanf ( "%d" , &m ) ;
while ( m -- ) {
scanf ( "%d" , &x ) ;
printf ( "%d\n" , search ( x ) ) ;
}
}
int main () {
while ( ~scanf ( "%d" , &n ) ) solve () ;
return 0 ;
}
C:Captain Marmot
题目大意:每个点有一个初始坐标以及一个中心轴坐标,该点可绕中心轴逆时针旋转90度,每旋转90度算一步移动。现在给你四个点,问最少需要多少步可以得到一个由这四个点旋转后的坐标(可以不旋转)构成的正方形。
首先我们知道每个点最多走三步,多了就回到原来的状态了。那么我们处理出每个点不走,走一步,走两步,走三步后的坐标,然后4*4*4*4判断是否有解,有解取步数最少。
#include
#include
#include
#include
using namespace std ;
typedef long long LL ;
#define rep( i , a , b ) for ( int i = a ; i < b ; ++ i )
#define For( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define rev( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i )
#define travel( e , H , u ) for ( Edge* e = H[u] ; e ; e = e -> next )
#define clr( a , x ) memset ( a , x , sizeof a )
#define cpy( a , x ) memcpy ( a , x , sizeof a )
#define ls ( o << 1 )
#define rs ( o << 1 | 1 )
#define lson ls , l , m
#define rson rs , m + 1 , r
#define root 1 , 1 , n
#define mid ( ( l + r ) >> 1 )
#define rt o , l , r
const int MAXN = 100005 ;
const int INF = 0x3f3f3f3f ;
struct Node {
int x , y ;
void input () {
scanf ( "%d%d" , &x , &y ) ;
}
void show () {
printf ( "%d %d\n" , x , y ) ;
}
} p[4][4] , home[4] ;
LL d[6] ;
LL dist ( const Node& a , const Node& b ) {
LL x = a.x - b.x ;
LL y = a.y - b.y ;
return x * x + y * y ;
}
void solve () {
int ans = INF ;
int flag = 0 ;
rep ( i , 0 , 4 ) {
p[i][0].input () ;
home[i].input () ;
p[i][3].x = home[i].x - home[i].y + p[i][0].y ;
p[i][3].y = home[i].y + home[i].x - p[i][0].x ;
p[i][2].x = home[i].x + home[i].x - p[i][0].x ;
p[i][2].y = home[i].y + home[i].y - p[i][0].y ;
p[i][1].x = home[i].x + home[i].x - p[i][3].x ;
p[i][1].y = home[i].y + home[i].y - p[i][3].y ;
}
//rep ( i , 0 , 4 ) p[2][i].show () ;
rep ( i , 0 , 4 ) {
rep ( j , 0 , 4 ) {
rep ( k , 0 , 4 ) {
rep ( l , 0 , 4 ) {
d[0] = dist ( p[0][i] , p[1][j] ) ;
d[1] = dist ( p[1][j] , p[2][k] ) ;
d[2] = dist ( p[2][k] , p[3][l] ) ;
d[3] = dist ( p[3][l] , p[0][i] ) ;
d[4] = dist ( p[0][i] , p[2][k] ) ;
d[5] = dist ( p[1][j] , p[3][l] ) ;
sort ( d , d + 6 ) ;
if ( d[0] == 0 ) continue ;
else if ( d[0] == d[1] && d[1] == d[2] && d[2] == d[3] && d[4] == 2 * d[0] && d[4] == d[5] ) {
flag = 1 ;
//p[0][i].show () ;
//p[1][j].show () ;
//p[2][k].show () ;
//p[3][l].show () ;
ans = min ( ans , i + j + k + l ) ;
}
}
}
}
}
if ( flag ) printf ( "%d\n" , ans ) ;
else printf ( "-1\n" ) ;
}
int main () {
int T ;
scanf ( "%d" , &T ) ;
while ( T -- ) solve () ;
return 0 ;
}
D:Flowers
每个白色花连续的数目一定是k的整数倍。
设dp[0][i]表示长度为i以白色花结尾的方案数,dp[1][i]表示长度为i以红色花结尾的方案数。
dp[0][i] = dp[0][i-k] + dp[1][i-k]
dp[1][i] = dp[0][i-1] + dp[1][i-1]
然后由于满足区间减法,我们求一遍前缀和预处理,每次询问O(1)输出。
#include
#include
#include
#include
using namespace std ;
typedef long long LL ;
#define rep( i , a , b ) for ( int i = a ; i < b ; ++ i )
#define For( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define rev( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i )
#define travel( e , H , u ) for ( Edge* e = H[u] ; e ; e = e -> next )
#define clr( a , x ) memset ( a , x , sizeof a )
#define cpy( a , x ) memcpy ( a , x , sizeof a )
#define ls ( o << 1 )
#define rs ( o << 1 | 1 )
#define lson ls , l , m
#define rson rs , m + 1 , r
#define root 1 , 1 , n
#define mid ( ( l + r ) >> 1 )
#define rt o , l , r
const int MAXN = 100005 ;
const int mod = 1e9 + 7 ;
int dp[2][MAXN] ;
int sum[MAXN] ;
int T , k ;
void fun () {
int tmp = 0 ;
clr ( dp , 0 ) ;
clr ( sum , 0 ) ;
dp[0][k] = 1 ;
For ( i , 1 , k ) dp[1][i] = 1 ;
tmp = 1 ;
For ( i , k + 1 , 100000 ) {
dp[0][i] = ( dp[1][i - k] + dp[0][i - k] ) % mod ;
dp[1][i] = ( tmp + 1 ) % mod ;
tmp = ( tmp + dp[0][i] ) % mod ;
}
For ( i , 1 , 100000 ) sum[i] = ( ( sum[i - 1] + dp[0][i] ) % mod + dp[1][i] ) % mod ;
}
void solve () {
int a , b ;
scanf ( "%d%d" , &a , &b ) ;
printf ( "%d\n" , ( sum[b] - sum[a - 1] + mod ) % mod ) ;
}
int main () {
scanf ( "%d%d" , &T , &k ) ;
fun () ;
while ( T -- ) solve () ;
return 0 ;
}
E:Pillars
首先将高度排序离散化,以离散化后的元素个数N为下标建立线段树,线段树每个下标表示一个高度,对于所有下标i
然后我们从左到右处理每个点(未离散化之前的点),对于第i个点,设其高度为hi,则我们在高度1~hi-K内找到一个最长长度,在hi+K~N内找到一个最长长度,取最优的一个,长度+1用以更新当前点,同时记录前驱。
#include
#include
#include
#include
using namespace std ;
typedef long long LL ;
#define rep( i , a , b ) for ( int i = a ; i < b ; ++ i )
#define For( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define rev( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i )
#define travel( e , H , u ) for ( Edge* e = H[u] ; e ; e = e -> next )
#define clr( a , x ) memset ( a , x , sizeof a )
#define cpy( a , x ) memcpy ( a , x , sizeof a )
#define ls ( o << 1 )
#define rs ( o << 1 | 1 )
#define lson ls , l , m
#define rson rs , m + 1 , r
#define root 1 , 1 , cnt
#define mid ( ( l + r ) >> 1 )
#define rt o , l , r
const int MAXN = 100005 ;
LL maxv[MAXN << 2] ;
int pos[MAXN << 2] ;
LL num[MAXN] ;
LL a[MAXN] , cnt ;
int pre[MAXN] ;
int S[MAXN] , top ;
int n , k ;
int unique ( int n ) {
int cnt = 1 ;
sort ( a + 1 , a + n + 1 ) ;
For ( i , 2 , n ) if ( a[i] != a[cnt] ) a[++ cnt] = a[i] ;
return cnt ;
}
int Rsearch ( LL x ) {
int l = 1 , r = cnt ;
while ( l < r ) {
int m = ( l + r ) / 2 ;
if ( a[m] >= x ) r = m ;
else l = m + 1 ;
}
return l ;
}
int Lsearch ( LL x ) {
int l = 1 , r = cnt ;
while ( l < r ) {
int m = ( l + r + 1 ) / 2 ;
if ( a[m] <= x ) l = m ;
else r = m - 1 ;
}
return r ;
}
void update ( int x , int v , int i , int o , int l , int r ) {
if ( l == r ) {
if ( v > maxv[o] ) {
maxv[o] = v ;
pos[o] = i ;
}
return ;
}
int m = mid ;
if ( x <= m ) update ( x , v , i , lson ) ;
else update ( x , v , i , rson ) ;
if ( maxv[ls] > maxv[rs] ) {
pos[o] = pos[ls] ;
maxv[o] = maxv[ls] ;
} else {
pos[o] = pos[rs] ;
maxv[o] = maxv[rs] ;
}
}
int query_max , query_pos ;
void query ( int L , int R , int o , int l , int r ) {
if ( L > R ) return ;
if ( L <= l && r <= R ) {
if ( query_max < maxv[o] ) {
query_max = maxv[o] ;
query_pos = pos[o] ;
}
return ;
}
int m = mid ;
if ( L <= m ) query ( L , R , lson ) ;
if ( m < R ) query ( L , R , rson ) ;
}
void print ( int n ) {
if ( pre[n] ) print ( pre[n] ) ;
S[top ++] = n ;
}
void solve () {
int max_len = 1 , idx = 1 ;
clr ( maxv , 0 ) ;
clr ( pre , 0 ) ;
For ( i , 1 , n ) scanf ( "%I64d" , &num[i] ) , a[i] = num[i] ;
cnt = unique ( n ) ;
update ( Lsearch ( num[1] ) , 1 , 1 , root ) ;
pre[1] = 0 ;
For ( i , 2 , n ) {
int L = Lsearch ( num[i] - k ) ;
int R = Rsearch ( num[i] + k ) ;
query_max = 0 , query_pos = 0 ;
if ( a[L] + k <= num[i] ) {
//printf ( "%I64d %I64d\n" , num[i] , a[L] ) ;
query ( 1 , L , root ) ;
}
if ( num[i] + k <= a[R] ) {
//printf ( "%I64d %I64d\n" , num[i] , a[R] ) ;
query ( R , cnt , root ) ;
}
update ( Lsearch ( num[i] ) , query_max + 1 , i , root ) ;
pre[i] = query_pos ;
if ( query_max + 1 > max_len ) {
max_len = query_max + 1 ;
idx = i ;
}
}
printf ( "%d\n" , max_len ) ;
top = 0 ;
print ( idx ) ;
rep ( i , 0 , top ) printf ( "%d%c" , S[i] , i < top - 1 ? ' ' : '\n' ) ;
}
int main () {
while ( ~scanf ( "%d%d" , &n , &k ) ) solve () ;
return 0 ;
}
F:Ant colony
又是线段树,不过比E还简单。
我们可以知道如果区间【L,R】内所有数的gcd!=该区间内最小的数minv,则对于区间内的每个数都至少有一个数不是其倍数,那么每个数的v值都不可能等于r-l,所以所有的蚂蚁都要被吃掉(统统吃掉)。
现在如果gcd=minv,那么对于所有的等于minv的数,所有的数都是他的倍数,对于所有的不等于minv的数,至少有一个不是他的倍数(比如minv),所以答案就是r-l+1-minv的个数。
既然明白了原理,那么我们就好做了。
建立一棵线段树,维护区间gcd,区间内最小值以及最小值出现的次数即可。
#include
#include
#include
#include
using namespace std ;
typedef long long LL ;
#define rep( i , a , b ) for ( int i = a ; i < b ; ++ i )
#define For( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define rev( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i )
#define travel( e , H , u ) for ( Edge* e = H[u] ; e ; e = e -> next )
#define clr( a , x ) memset ( a , x , sizeof a )
#define cpy( a , x ) memcpy ( a , x , sizeof a )
#define ls ( o << 1 )
#define rs ( o << 1 | 1 )
#define lson ls , l , m
#define rson rs , m + 1 , r
#define root 1 , 1 , n
#define mid ( ( l + r ) >> 1 )
#define rt o , l , r
const int MAXN = 100005 ;
const int INF = 0x3f3f3f3f ;
int minv[MAXN << 2] ;
int num[MAXN << 2] ;
int GCD[MAXN << 2] ;
int n ;
int gcd ( int a , int b ) {
return b ? gcd ( b , a % b ) : a ;
}
void build ( int o , int l , int r ) {
if ( l == r ) {
scanf ( "%d" , &minv[o] ) ;
num[o] = 1 ;
GCD[o] = minv[o] ;
return ;
}
int m = mid ;
build ( lson ) ;
build ( rson ) ;
if ( minv[ls] < minv[rs] ) {
minv[o] = minv[ls] ;
num[o] = num[ls] ;
} else if ( minv[ls] > minv[rs] ) {
minv[o] = minv[rs] ;
num[o] = num[rs] ;
} else {
minv[o] = minv[ls] ;
num[o] = num[ls] + num[rs] ;
}
GCD[o] = gcd ( GCD[ls] , GCD[rs] ) ;
}
int query_min , query_num , query_gcd ;
void query ( int L , int R , int o , int l , int r ) {
if ( L <= l && r <= R ) {
if ( query_min > minv[o] ) {
query_min = minv[o] ;
query_num = num[o] ;
} else if ( query_min == minv[o] ) query_num += num[o] ;
query_gcd = gcd ( query_gcd , GCD[o] ) ;
return ;
}
int m = mid ;
if ( L <= m ) query ( L , R , lson ) ;
if ( m < R ) query ( L , R , rson ) ;
}
void solve () {
int m , l , r ;
build ( root ) ;
scanf ( "%d" , &m ) ;
while ( m -- ) {
scanf ( "%d%d" , &l , &r ) ;
query_min = INF ;
query_num = 0 ;
query_gcd = 0 ;
query ( l , r , root ) ;
if ( query_gcd != query_min ) printf ( "%d\n" , r - l + 1 ) ;
else printf ( "%d\n" , r - l + 1 - query_num ) ;
}
}
int main () {
while ( ~scanf ( "%d" , &n ) ) solve () ;
return 0 ;
}