LG11725
读题可以发现,一个大的区间的答案是由三个小的区间的答案决定的。同时又要支持单点修改,因此可以用一个数据结构维护,比如线段树。在这个线段树中,每个非叶子节点有三个子节点。先建好原始的树,修改时定位到叶子节点,再向上更新答案即可,与普通线段树的操作类似。
时间复杂度 \(O(n+q\log n)\)。
#include <iostream>
#include <cstdio>
#define N 5000001
using namespace std;
struct T
{
int s1,s2,s3,v;
}t[N];
int n = 1,a[N],tot = 1;
void pushup( int u )
{
int cnt[2] = {0};
cnt[t[t[u].s1].v] ++,cnt[t[t[u].s2].v] ++,cnt[t[t[u].s3].v] ++;
if( cnt[0] > cnt[1] ) t[u].v = 0;
else t[u].v = 1;
}
void build( int u , int l , int r )
{
if( l == r )
{
t[u].v = a[l];
return;
}
t[u].s1 = ++ tot;t[u].s2 = ++ tot,t[u].s3 = ++ tot;
int len = ( r - l + 1 ) / 3;
build( t[u].s1 , l , l + len - 1 );
build( t[u].s2 , l + len , r - len );
build( t[u].s3 , r - len + 1 , r );
pushup( u );
}
void update( int u , int l , int r , int p , int v )
{
if( l == r )
{
t[u].v = v;
return;
}
int len = ( r - l + 1 ) / 3;
if( p <= l + len - 1 ) update( t[u].s1 , l , l + len - 1 , p , v );
else if( p >= r - len + 1 ) update( t[u].s3 , r - len + 1 , r , p , v );
else update( t[u].s2 , l + len , r - len , p , v );
pushup( u );
return;
}
int main()
{
int T,ti,k;
string s;
cin >> ti >> T;
cin >> s;
while( ti -- )
n *= 3;
for( int i = 1 ; i <= n ; i ++ )
a[i] = s[i - 1] - 'A';
build( 1 , 1 , n );
while( T -- )
{
cin >> k;
update( 1 , 1 , n , k , 1 - a[k] );
a[k] = 1 - a[k];
putchar( t[1].v + 'A' );putchar( '\n' );
}
return 0;
}

浙公网安备 33010602011771号