Problem statement
首先要发现一个性质:
如果一个三进制数如下:
. . . . . . 0
它加1后变为
. . . . . . 1
所以
…0 +1=…1
…1 +1=…2
…2 +1=…10
…10+1=…11
可以建立一棵trie:
s
0 1 2
0 1 2 0 1 2 0 1 2
......................
其中每一个叶子的值都是从s走到这个叶子所够成的三进制数(从上往下代表三进制的低位到高位!)
所以+1的操作就是从s开始把每一条边上的值都+1 并%3.
然后再递归原来值为2的边指向的儿子节点。这样就可以再
O
(
n
)
O(n)
O(n) 的时间内完成+1操作。
然后
1
−
>
2
,
2
−
>
1
1->2,2->1
1−>2,2−>1的操作可以再每一个trie的节点上打上lazy tag 。如果处理到就把1的边上的值变成2,2的边的值变为1,再push_down就行了.
总复杂读
O
(
n
∗
∣
T
∣
)
O(n*|T|)
O(n∗∣T∣)
代码:
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define KEEP while(1)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define debug_pair(A) cerr<<A.FIR<<" "<<A.SEC<<endl;
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
typedef pair<mp,mp> superpair;
int N,LOGN,n;
struct node{
int val;
vector<mp> sons;
bool flag;
void push_down(){
if(!flag||sons.empty()){
return;
}
flag=0;
int i1,i2;
rep(i,3)
if(sons[i].FIR==1) i1=i;
rep(i,3)
if(sons[i].FIR==2) i2=i;
swap(sons[i1].FIR,sons[i2].FIR);
}
}trie[2000000];
void gao(int index){
trie[index].flag^=1;
}
int cnt=1;
int b[13];
void build(int now,int depth,int val){
if(depth==LOGN+1) {
// cout<<now<<" "<<val<<endl;
trie[now].val=val;
return;
}
trie[now].sons.PB(II(0,++cnt));
build(cnt,depth+1,val);
trie[now].sons.PB(II(1,++cnt));
build(cnt,depth+1,val+b[-1+depth]);
trie[now].sons.PB(II(2,++cnt));
build(cnt,depth+1,val+b[-1+depth]*2);
}
void modify(int now){
// cout<<"!" <<now<<endl;
if(trie[now].sons.empty()) return;
if(trie[now].flag){
trie[now].push_down();
rep(i,3)
gao(trie[now].sons[i].SEC);
}
rep(i,3)
{
trie[now].sons[i].FIR++;
trie[now].sons[i].FIR%=3;
if(!trie[now].sons[i].FIR){
modify(trie[now].sons[i].SEC);
}
}
}
int res[600000];
void recover(int now,int pos,int depth){
if(trie[now].sons.empty()){
res[trie[now].val]=pos;
}
else{
if(trie[now].flag){
trie[now].push_down();
rep(i,3)
gao(trie[now].sons[i].SEC);
}
rep(i,3){
recover(trie[now].sons[i].SEC,pos+b[depth-1]*trie[now].sons[i].FIR,depth+1);
}
}
}
int main(){
fastio;
cin>>N;
n=1;
rb(i,1,N) n*=3;
b[0]=1;
rb(i,1,N)
b[i]=b[i-1]*3;
LOGN=N;
N=n;
build(1,1,0);
string T="";
cin>>T;
rep(INDEX,T.length()){
bool ty=(T[INDEX]=='S');
if(ty){
trie[1].flag^=1;
}
else{
modify(1);
}
}
recover(1,0,1);
rb(i,0,N-1)
cout<<res[i]<<" ";
return 0;
}