【HDU】BestCoder Round #11 (Div. 2)

本文精选了几道算法竞赛题目并提供了详细的解题思路与代码实现,包括简单的数学判断、排序与特殊输出、双端队列滑动窗口计数以及树状数组区间查询等技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

5054:Alice and Bob


只要x*2==n&&y*2==m就输出YES,否则输出NO。


5055:Bob and math problem


先找到最小的一个奇数,提取出来,没有奇数输出-1。然后拍个序,看最大的数是不是大于0,如果是,倒序输出排序后的每个数,再输出提取出来的奇数,否则输出-1。


5056:Boring count


双端队列。从左到右扫描每个字母,每个字母扫描到后,如果这时所有【l,r】内的字母个数都不超过K,则以这个字母为结尾的总数为r-l+1,否则,滑动l,直到【l',r】内的所有字母个数都不超过K为止,然后总数即r-l'+1。


5057:Argestes and Sequence


这题我脑筋没转过来,总想着在线做。。结果用了short类型的10*10*100005的树状数组(没考虑到short只有32768,远不到100000,wa了)。赛后用unsigned short加一个标记数组2484ms卡过一次(之后再没过过),标记就如果超过50000我就标记一下,然后树状数组的数减50000就好,最后统计的时候再加上就好(我看到比赛时有的人也是这个方法AC的,但是他的方法貌似是错的,因为如果减的时候总数小于50000时是要把标记清除的,他没考虑到)。

现在我讲一下另一个看起来更加靠谱的方法:

将操作保存下来,然后开一个10*100005的数组,10表示开头数字。因为所有位上的操作以及查询均是独立的,所以我们从右到左每一位重新做一次所有的操作即可,当然,修改是必须进行的,而查询只要执行相关的即可。

最后的跑了1187ms。


附上AC代码。


代码如下:


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
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 )

const int MAXN = 100005 ;

struct Query {
	int op ;
	int x , y , d , p ;
} query[MAXN] ;

int ans[MAXN] ;
int num[MAXN][11] ;
int T[10][MAXN] ;
int n , q ;

void add ( int x , int digit , int v ) {
	while ( x <= n ) {
		T[digit][x] += v ;
		x += x & -x ;
	}
}

int sum ( int x , int digit , int ans = 0 ) {
	while ( x ) {
		ans += T[digit][x] ;
		x -= x & -x ;
	}
	return ans ;
}

void solve () {
	int x ;
	char buf[5] ;
	scanf ( "%d%d" , &n , &q ) ;
	clr ( ans , -1 ) ;
	For ( i , 1 , n ) {
		scanf ( "%d" , &x ) ;
		For ( j , 1 , 10 ) {
			num[i][j] = x % 10 ;
			x /= 10 ;
		}
	}
	rep ( i , 0 , q ) {
		scanf ( "%s" , buf ) ;
		if ( buf[0] == 'S' ) {
			scanf ( "%d%d" , &query[i].x , &query[i].y ) ;
			query[i].op = 0 ;
		} else {
			scanf ( "%d%d%d%d" , &query[i].x , &query[i].y , &query[i].d , &query[i].p ) ;
			query[i].op = 1 ;
		}
	}
	For ( j , 1 , 10 ) {
		clr ( T , 0 ) ;
		For ( i , 1 , n ) add ( i , num[i][j] , 1 ) ;
		rep ( i , 0 , q ) {
			if ( query[i].op == 0 ) {
				int x = query[i].x ;
				add ( x , num[x][j] , -1 ) ;
				num[x][j] = query[i].y % 10 ;
				add ( x , num[x][j] , 1 ) ;
				query[i].y /= 10 ;
			} else {
				if ( query[i].d != j ) continue ;
				int l = query[i].x , r = query[i].y ;
				ans[i] = sum ( r , query[i].p ) - sum ( l - 1 , query[i].p ) ;
			}
		}
	}
	rep ( i , 0 , q ) if ( ~ans[i] ) printf ( "%d\n" , ans[i] ) ;
}

int main () {
	//freopen ( "out.txt" , "r" , stdin ) ;
	int T ;
	while ( ~scanf ( "%d" , &T ) ) {
		while ( T -- ) solve () ;
	}
	return 0 ;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值