HDU多校 - three arrays(字典树+bfs)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6625
题意
给出两个数组A,B求任意交换A数组中的顺序和B数组中的数组,求两者对应异或的C数组字典序最小
数据范围: 1 ≤ N ≤ 1 0 5 1\le N \le 10^5 1≤N≤105
思路
我们将A数组的数据全部转换成为01串,插入字典树A中,将B数组中的数据全部转换成为01串插入字典树B中。
将两个树同时BFS,显然前缀相等的越多越好,我们就将其分成三类,
- 两棵树同时向左边移动
- 两棵树同时向右边移动
- 两棵树互相反向移动
我们需要做的就是将状态记录下来,方便转移。
因为最多会有N种状态,所以BFS的复杂度就是 O ( N l o g N ) O(NlogN) O(NlogN)
一定要注意,字典树开的大小,为 O ( N ∗ l e n ) O(N*len) O(N∗len) ,千万不要少,这次就是因为少开了空间而一直T。
代码
#include <bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define debug(x) cerr<<#x<<":"<<x<<endl
#define pb push_back
void test(){cerr<<"\n";}
template<typename T,typename... Args>void test(T x,Args... args){cerr<<x<<" ";test(args...);}
typedef double db;
typedef long long ll;
const int MAXN = (int)1e6+7;
const int MaxTot = 5e6+7;
const int INF = (int)0x3f3f3f3f;
struct Aho {
struct state{
int next[2];
int cnt,fa,vis;
}tree[MaxTot];
int tot;
inline void init(int lun) {
tree[0].next[0] = tree[0].next[1] = 0;
tree[0].cnt = tree[0].fa = tree[0].vis = 0;
tree[1].next[0] = tree[1].next[1] = 0;
tree[1].cnt = tree[1].fa = 0;
tree[1].vis = lun;
tot = 1;
}
inline void insert(char *S,int lun) { //构造字典树,插入S这个串
int n = strlen(S);
int now = 1;
tree[now].cnt ++;
rep(i,0,n-1) { //提取出每个字符
char c = S[i]-'0';
if (tree[tree[now].next[c]].vis != lun) {
tree[now].next[c] = ++tot;
int son = tot;
tree[son].cnt = 1;
tree[son].fa = now;
tree[son].next[0] = tree[son].next[1] = 0;
tree[son].vis = lun;
}else {
tree[tree[now].next[c]].cnt ++;
}
now = tree[now].next[c];
}
//tree[now].cnt++; //走到了结束位置,最后++
}
}a,b;
int N;
char str[50];
int valA[MAXN];
int valB[MAXN];
inline void toString(int tmp) {
int len = 0;
if (tmp == 0) str[len++] = '0';
while (tmp) {
int to = tmp%2;
str[len++] = to+'0';
tmp>>=1;
}
rep(i,len,29) {
str[i] = '0';
}
rep(i,0,14) swap(str[i],str[29-i]);
str[30] = 0;
}
struct Node{
int l,r,cnt,dep;
ll val;
Node(int l = 0,int r = 0,ll val = 0,int cnt = 0,int dep = 0):l(l),r(r),val(val),cnt(cnt),dep(dep){}
};
vector<int> ans;
inline ll set1(ll x,int id) {
ll res = x;
res |= 1LL<<(30-id);
return res;
}
inline void getAnum(int id,int &l,int &r,int &lid,int &rid) {
int tl = a.tree[id].next[0];
int tr = a.tree[id].next[1];
int lun = a.tree[id].vis;
if (a.tree[tl].vis != lun) l = 0;
else l = a.tree[tl].cnt;
if (a.tree[tr].vis != lun) r = 0;
else r = a.tree[tr].cnt;
lid = tl;
rid = tr;
}
inline void getBnum(int id,int &l,int &r,int &lid,int &rid) {
int tl = b.tree[id].next[0];
int tr = b.tree[id].next[1];
int lun = b.tree[id].vis;
if (b.tree[tl].vis != lun) l = 0;
else l = b.tree[tl].cnt;
if (b.tree[tr].vis != lun) r = 0;
else r = b.tree[tr].cnt;
lid = tl;
rid = tr;
}
inline void setAnum(int id,int l,int r) {
int tl = a.tree[id].next[0];
int tr = a.tree[id].next[1];
int lun = a.tree[id].vis;
a.tree[tl].cnt = l;
a.tree[tr].cnt = r;
}
inline void setBnum(int id,int l,int r) {
int tl = b.tree[id].next[0];
int tr = b.tree[id].next[1];
int lun = b.tree[id].vis;
b.tree[tl].cnt = l;
b.tree[tr].cnt = r;
}
queue<Node> qu;
void bfs(int N) {
while (!qu.empty()) qu.pop();
qu.push(Node(1,1,0,N,0));
while (!qu.empty()) {
Node k = qu.front();qu.pop();
if (k.dep == 30) {
rep(i,1,k.cnt) {
ans.pb(k.val);
}
continue;
}
int cnt = k.cnt;
int anum0,anum1,alid,arid;
int bnum0,bnum1,blid,brid;
getAnum(k.l,anum0,anum1,alid,arid);
getBnum(k.r,bnum0,bnum1,blid,brid);
int mn0 = min(cnt,min(anum0,bnum0)); cnt -= mn0;
int mn1 = min(cnt,min(anum1,bnum1)); cnt -= mn1;
anum0 -= mn0;bnum0 -= mn0;
anum1 -= mn1;bnum1 -= mn1;
int giv01 = min(cnt,min(anum0,bnum1));cnt -= giv01;
int giv10 = min(cnt,min(anum1,bnum0));cnt -= giv10;
anum0 -= giv01;bnum1 -= giv01;
anum1 -= giv10;bnum0 -= giv10;
if (mn0) {
ll sta = k.val;
Node to = Node(alid,blid,sta,mn0,k.dep+1);
qu.push(to) ;
}
if (mn1) {
ll sta = k.val;
Node to = Node(arid,brid,sta,mn1,k.dep+1);
qu.push(to);
}
if (giv01) {
ll sta = set1(k.val,k.dep+1);
Node to = Node(alid,brid,sta,giv01,k.dep+1);
qu.push(to) ;
}
if (giv10) {
ll sta = set1(k.val,k.dep+1);
Node to = Node(arid,blid,sta,giv10,k.dep+1);
qu.push(to);
}
setAnum(k.l,anum0,anum1);
setBnum(k.r,bnum0,bnum1);
}
}
int main()
{
int T;
scanf("%d",&T);
rep(ca,1,T) {
a.init(ca);//不必每次都有
b.init(ca);
ans.clear();
scanf("%d",&N);
rep(i,1,N) {
scanf("%d",&valA[i]);
toString(valA[i]);
//debug(str);
a.insert(str,ca);
}
rep(i,1,N) {
scanf("%d",&valB[i]);
toString(valB[i]);
//debug(str);
b.insert(str,ca);
}
bfs(N);
sort(ans.begin(),ans.end());
rep(i,0,ans.size()-1) {
printf("%d%c",ans[i],(i==ans.size()-1?'\n':' '));
}
}
}