zoukankan      html  css  js  c++  java
  • hdu 6625 three array (01-trie)

    大意: 给两个数组$a,b$, 要求重排使得$c_i=a_ioplus b_i$字典序最小.

    字典树上贪心取$n$次, 然后排序, 还不知道怎么证. 

    #include <iostream>
    #include <sstream>
    #include <algorithm>
    #include <cstdio>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    #include <cstring>
    #include <bitset>
    #include <functional>
    #include <random>
    #define REP(i,a,n) for(int i=a;i<=n;++i)
    #define PER(i,a,n) for(int i=n;i>=a;--i)
    #define hr putchar(10)
    #define pb push_back
    #define lc (o<<1)
    #define rc (lc|1)
    #define mid ((l+r)>>1)
    #define ls lc,l,mid
    #define rs rc,mid+1,r
    #define x first
    #define y second
    #define io std::ios::sync_with_stdio(false)
    #define endl '
    '
    using namespace std;
    const int N = 1e5+50, S = 29;
    int n, T[2], tot;
    struct {int ch[2];} tr[N*60];
    int cnt[N*60][2];
    vector<int> ans;
    void add(int &o, int d, int x, int tp, int v) {
    	if (!o) o=++tot;
    	cnt[o][tp]+=v;
    	if (d>=0) add(tr[o].ch[x>>d&1],d-1,x,tp,v);
    }
    void solve(int u, int v, int d, int x, int y) {
    	--cnt[u][0],--cnt[v][1];
    	if (d<0) return ans.pb(x^y);
    	int A=cnt[tr[u].ch[0]][0],B=cnt[tr[u].ch[1]][0];
    	int C=cnt[tr[v].ch[0]][1],D=cnt[tr[v].ch[1]][1];
    	if (A&&C) return solve(tr[u].ch[0],tr[v].ch[0],d-1,x,y);
    	if (B&&D) return solve(tr[u].ch[1],tr[v].ch[1],d-1,x^1<<d,y^1<<d);
    	if (A&&D) return solve(tr[u].ch[0],tr[v].ch[1],d-1,x,y^1<<d);
    	if (B&&C) return solve(tr[u].ch[1],tr[v].ch[0],d-1,x^1<<d,y);
    }
    
    void work() {
    	scanf("%d", &n);
    	REP(z,0,1) REP(i,1,n) {
    		int t;
    		scanf("%d", &t);
    		add(T[z],S,t,z,1);
    	}
    	ans.clear();
    	REP(i,1,n) solve(T[0],T[1],S,0,0);
    	sort(begin(ans),end(ans));
    	REP(i,0,n-1) printf("%d%c",ans[i]," 
    "[i==n-1]);
    	T[0]=T[1]=0;
    	while (tot) cnt[tot][0]=cnt[tot][1]=tr[tot].ch[0]=tr[tot].ch[1]=0,--tot;
    }
    
    int main() {
    	int t;
    	scanf("%d", &t);
    	while (t--) work();
    }
    

     

  • 相关阅读:
    HDU 5213 分块 容斥
    HDU 2298 三分
    HDU 5144 三分
    HDU 5145 分块 莫队
    HDU 3938 并查集
    HDU 3926 并查集 图同构简单判断 STL
    POJ 2431 优先队列
    HDU 1811 拓扑排序 并查集
    HDU 2685 GCD推导
    HDU 4496 并查集 逆向思维
  • 原文地址:https://www.cnblogs.com/uid001/p/11413660.html
Copyright © 2011-2022 走看看