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;
}
posted @ 2025-09-08 18:43  FormulaOne  阅读(11)  评论(0)    收藏  举报