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。
这题我脑筋没转过来,总想着在线做。。结果用了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 ;
}