Problem:
Problem H
Artist in Agony
You, an artist, prepared a sufficient number of balls and also strings to link them for your artwork. Balls are to be given sequential numbers eventually, but only one of the balls is given number 1 at the beginning.  No other balls are numbered and no balls are linked to any other balls yet.
An artwork is created by carrying out either of the following actions repetitively.
Replication
:
The work in progress is replicated.  Let
n
be the number of balls numbered so far.  You pick
n
unnumbered balls and number them
n
+1, ..., 2
n
.  This results in 2
n
balls uniquely numbered 1 through 2
n.
Then for all pairs of balls linked directly before replication numbered
u
and
v,
the two balls newly numbered
n
+
u
and
n
+
v
are linked with a string.
Making a new link
:
Two distinct balls already numbered are chosen and linked with a string.  When two balls are already linked directly, this action does nothing.
Note that, as initially only one ball is numbered, you have to start with the replication action.
Figure H-1 shows the process of artwork creation of the second dataset in Sample Input.
Figure H-1: Artwork creation example
Being a perfectionist as with all the real artists, you cannot stand imperfect works.  When you find a work unsatisfactory, you have to destroy it completely as quick as possible by tearing off all the links in it.  You grab some of the numbered balls in one hand, the rest in the other hand, and pull them apart tearing off all the strings linking the balls in your right hand and the balls in your left hand.  If all the strings linking the balls are torn off by doing this operation just once, your destruction is successful. Conversely, any remaining links between two balls in one hand mean that the destruction is a failure.
Figure H-2 shows the work of the second dataset in Sample Input being destroyed. To destroy the work, you have to grab three or more balls in each of your hands.
Figure H-2: Destructing the artwork described above
Given the sequence of actions that created the work, judge whether you can destroy it in the way described above.  If you can, find the minimum number of balls you have to grab in your left hand. You may grab an arbitrary number of balls in your right hand.
Input
The input consists of multiple datasets, each in the following format.
m
a
1
⋮
a
m
m
is the number of actions you have carried out.
m
is a positive integer and does not exceed 300.
The
i
-th action
a
i
(
i
= 1, ...,
m
) is given by either of the following forms.
COPY
This represents the
Replication
action in the problem statement. It is guaranteed that each dataset contains no more than 60
COPY
actions.
LINK
u
v
This represents the
Making a new link
action in the problem statement. In this action, the two balls numbered
u
and
v
were inspected, and a new link between them was made if they had not been directly connected yet.
u
and
v
are positive integers that satisfy
u < v
. It is guaranteed that two balls had already be
...(truncated)

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
using uint = unsigned int;
#define rep(i, n) for (int i = 0; i < n; i++)
#define all(v) v.begin(), v.end()
template <class T, class U>
inline bool chmax(T& a, U b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}
template <class T, class U>
inline bool chmin(T& a, U b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
template <class T>
inline void compress(vector<T>& a) {
    sort(a.begin(), a.end());
    a.erase(unique(a.begin(), a.end()), a.end());
}
template <class T>
T rand(T l, T r) {
    static mt19937 mt(random_device{}());
    // [l, r)
    if constexpr (is_integral_v<T>) {
        return uniform_int_distribution<T>(l, r - 1)(mt);
    } else if constexpr (is_floating_point_v<T>) {
        return uniform_real_distribution<T>(l, r)(mt);
    }
}
constexpr int INF = 1001001001;
constexpr ll llINF = 3000000000000000010;

struct UnionFind {
    vector<int> par;
    vector<ll> siz;
    vector<ll> A, B;
    UnionFind(int x) {
        par.resize(x);
        siz.resize(x);
        A.resize(x);
        B.resize(x);
        for (int i = 0; i < x; i++) {
            par[i] = i;
            siz[i] = 1;
            A[i] = (i < x / 2);
            B[i] = (i >= x / 2);
        }
    }
    int find(int x) {
        if (par[x] == x) return x;
        return par[x] = find(par[x]);
    }
    bool unite(int x, int y) {
        x = find(x), y = find(y);
        if (x == y) return false;
        if (siz[x] < siz[y]) swap(x, y);
        par[y] = x;
        siz[x] += siz[y];
        A[x] += A[y];
        B[x] += B[y];
        return true;
    }
    bool same(int x, int y) { return find(x) == find(y); }
    int size(int x) { return siz[find(x)]; }
};
void solve() {
    int m;
    cin >> m;
    if (m == 0) exit(0);
    vector<string> str(m);
    vector<ll> u(m), v(m);
    map<ll, int> mp;
    mp[0] = 0;
    rep(i, m) {
        cin >> str[i];
        if (str[i] == "LINK") {
            cin >> u[i] >> v[i];
            u[i]--, v[i]--;
            for (ll y : {u[i], v[i]}) {
                while (y) {
                    mp[y] = 0;
                    int d = 63 - __builtin_clzll(y);
                    y &= ~(1LL << d);
                }
            }
        }
    }
    int CC = count(all(str), "COPY");
    int T = 0;
    vector<vector<ll>> xs(62);
    vector<ll> vec;
    for (auto [y, idx] : mp) {
        vec.push_back(y);
        mp[y] = T++;
        if(y==0)continue;
        int d = 63 - __builtin_clzll(y);
        xs[d].push_back(y);
    }
    UnionFind uf(T * 2);
    int d = 0;
    ll ans = 0;
    rep(i, m) {
        if (str[i] == "COPY") {
            ans *= 2;
            map<int, vector<int>> gr;
            for (ll y : xs[d]) {
                ll z = y & ~(1LL << d);
                gr[uf.find(mp[z])].push_back(mp[y]);
                gr[uf.find(mp[z] + T)].push_back(mp[y] + T);
            }
            // 元のrootごとに新しい頂点を記録
            for (auto [root, vs] : gr) {
                uf.par[vs[0]] = vs[0];
                uf.siz[vs[0]] = uf.siz[root];
                uf.A[vs[0]] = uf.A[root];
                uf.B[vs[0]] = uf.B[root];
                rep(j, (int)vs.size() - 1) uf.par[vs[j + 1]] = vs[0];
            }
            d++;
        } else {
            if (uf.same(mp[u[i]], mp[v[i]])) {
                cout << -1 << endl;
                return;
            }
            if (uf.same(mp[u[i]], mp[v[i]] + T)) continue;
            ans -= min(uf.A[uf.find(mp[u[i]])], uf.B[uf.find(mp[u[i]])]);
            ans -= min(uf.A[uf.find(mp[v[i]] + T)], uf.B[uf.find(mp[v[i]] + T)]);
            uf.unite(mp[u[i]], mp[v[i]] + T);
            uf.unite(mp[u[i]] + T, mp[v[i]]);
            ans += min(uf.A[uf.find(mp[u[i]])], uf.B[uf.find(mp[u[i]])]);
        }
    }
    rep(i, T) {
        if (uf.same(i, i + T)) {
            cout << -1 << endl;
            return;
        }
    }
    cout << ans << endl;
}
int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    int t = 1;
    // cin >> t;
    while (1) solve();
}
accuracy: 1
time_ms: 250
memory_kb: 4244
final_rank: 2

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pi;
#define FOR(i,l,r) for(ll i=l;i<r;i++)
#define REP(i,n) FOR(i,0,n)
#define RFOR(i,l,r) for(ll i=r-1;i>=l;i--)
#define RREP(i,n) RFOR(i,0,n)
#define ALL(A) A.begin(),A.end()
#define LB(A,x) (ll)(lower_bound(A.begin(),A.end(),x)-A.begin())
ll solve(vector<vector<pi>>A){
    auto B=A;
    ll M=A.size();
    vector<vector<ll>>vs(M);
    vector<vector<pi>>nec(M);
    auto leader=[&](ll v,ll j){
        ll id=LB(vs[j],v%(1LL<<(j+2)));
        assert(vs[j][id]==v%(1LL<<(j+2)));
        while(1){
            if(nec[j][id].first+nec[j][id].second<0)return ((v>>(j+2))<<(j+2))+vs[j][id];
            id=nec[j][id].first;
        }
    };
    REP(i,M){
        FOR(j,i,M)for(auto[u,v]:A[j]){
            vs[i].emplace_back(u%(1LL<<(i+2)));
            vs[i].emplace_back(v%(1LL<<(i+2)));
        }
        sort(ALL(vs[i]));
        vs[i].erase(unique(ALL(vs[i])),vs[i].end());
        for(auto v:vs[i]){
            if(i&&binary_search(ALL(vs[i-1]),v%(1LL<<(i+1)))){
                ll t=LB(vs[i-1],v%(1LL<<(i+1)));
                assert(nec[i-1][t].first+nec[i-1][t].second<0);
                nec[i].emplace_back(nec[i-1][t]);
            }
            else nec[i].emplace_back(v%2?pi(0,-1):pi(-1,0));
        }
        vector<ll>real(vs[i].size(),-1);
        for(auto[u,v]:A[i]){
            ll idu=LB(vs[i],u),idv=LB(vs[i],v);
            while(1){
                if(real[idu]<0)break;
                idu=real[idu];
            }
            while(1){
                if(real[idv]<0)break;
                idv=real[idv];
            }
            if(idu==idv)continue;
            if(real[idu]<real[idv])swap(idu,idv);
            nec[i][idu].first+=nec[i][idv].first;
            nec[i][idu].second+=nec[i][idv].second;
            nec[i][idv].first=idu;
            nec[i][idv].second=0;
            real[idu]+=real[idv];
            real[idv]=idu;
        }
        FOR(j,i+1,M)for(auto&[u,v]:A[j]){
            u=leader(u,i);
            v=leader(v,i);
        }
    }
    ll ans=0;
    REP(i,M)REP(j,vs[i].size())if(nec[i][j].first+nec[i][j].second<0){
        ll a=min(-nec[i][j].first,-nec[i][j].second);
        if(i==M-1)ans+=a;
        else{
            if(!binary_search(ALL(vs[i+1]),vs[i][j]+(1LL<<(i+2))))ans+=a<<(M-2-i);
            if(!binary_search(ALL(vs[i+1]),vs[i][j]))ans+=a<<(M-2-i);
        }
    }
    REP(i,M)for(auto[u,v]:B[i]){
        u=u/2*2,v=u+1;
        REP(j,i+1)u=leader(u,j),v=leader(v,j);
        if(u==v)return -1;
    }
    assert(ans%2==0);
    return ans/2;
}
int main(){
    while(1){
        ll Q;cin>>Q;
        if(!Q)return 0;
        vector<vector<pi>>A;
        while(Q--){
            string S;cin>>S;
            if(S[0]=='C')A.emplace_back(vector<pi>{});
            else{
                ll u,v;cin>>u>>v;u--;v--;
                A.back().emplace_back(pi(2*u,2*v+1));
                A.back().emplace_back(pi(2*v,2*u+1));
            }
        }
        cout<<solve(A)<<endl;
    }
    return 0;
}
accuracy: 1
time_ms: 430
memory_kb: 4380
final_rank: 3

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

struct UnionFind{
    vector<int> par; int n;
    vector<ll> ans;
    UnionFind(){}
    UnionFind(int _n):par(_n,-1),n(_n){
        ans.resize(_n,0);
        rep(i,_n/2,_n) ans[i] = 1;
    }
    int root(int x){
        if (par[x] < 0) return x;
        else {
            int r = root(par[x]);
            par[x]=r;
            return r;
        }
    }
    bool same(int x,int y){return root(x)==root(y);}
    int size(int x){return -par[root(x)];}
    ll answer(int x){
        return ans[root(x)];
    }
    void change(int x, ll a) {
        x = root(x);
        ans[x] = a;
    }
    bool unite(int x,int y){
        x=root(x),y=root(y); if(x==y)return false;
        if(size(x)>size(y))swap(x,y);
        ans[y]+=ans[x], par[y]+=par[x]; par[x]=y;
        return true;
    }
};

/**
 * @brief Union Find
 */

struct Query {
    ll Type, A, B;
};

ll Solve(int N) {
    vector<Query> Q(N);
    ll X = 1;
    rep(i,0,N) {
        string S;
        cin >> S;
        if (S == "COPY") Q[i].Type = 0, X *= 2;
        else Q[i].Type = 1, cin >> Q[i].A >> Q[i].B, Q[i].A--, Q[i].B--;
    }
    vector<ll> AS;
    rep(i,0,N) {
        if (Q[i].Type == 0) continue;
        ll Cur = Q[i].A;
        while(1) {
            AS.push_back(Cur);
            if (Cur == 0) break;
            Cur -= (1LL<<topbit(Cur));
        }
        Cur = Q[i].B;
        while(1) {
            AS.push_back(Cur);
            if (Cur == 0) break;
            Cur -= (1LL<<topbit(Cur));
        }
    }
    UNIQUE(AS);
    int M = AS.size();
    rep(i,0,M) AS.push_back(AS[i] + X);
    UnionFind UF(M*2);
    ll ANS = 0, CurSize = 1;
    rep(i,0,N) {
        if (Q[i].Type == 0) {
            ANS *= 2;
            map<int, vector<int>> mp;
            rep(j,0,M) {
                if (CurSize <= AS[j] & AS[j] < CurSize * 2) {
                    int ID = LB(AS, AS[j] - CurSize);
                    int Root = UF.root(ID);
                    if (mp.count(Root)) mp[Root].push_back(j);
                    else mp[Root] = {j};
                    ID += M;
                    Root = UF.root(ID);
                    if (mp.count(Root)) mp[Root].push_back(j+M);
                    else mp[Root] = {j+M};
                }
            }
            for (auto it = mp.begin(); it != mp.end(); it++) {
                auto V = it->second;
                if (V.size() == 1) continue;
                rep(j,0,V.size()-1) UF.unite(V[j], V[j+1]);
            }
            rep(j,0,M) {
                if (CurSize <= AS[j] && AS[j] < CurSize * 2) {
                    int ID = LB(AS, AS[j] - CurSize);
                    UF.change(j,UF.answer(ID));
                    UF.change(j+M,UF.answer(ID+M));
                }
            }
            CurSize *= 2;
        }
        else {
            ll A = Q[i].A, B = Q[i].B;
            int AID = LB(AS,A), BID = LB(AS,B);
            if (UF.same(AID,BID)) {
                return -1;
            }
            if (UF.same(AID,BID+M)) continue;
            ANS -= min(UF.answer(AID), UF.answer(AID+M));
            ANS -= min(UF.answer(BID), UF.answer(BID+M));
            UF.unite(AID, BID+M);
            UF.unite(AID+M, BID);
            ANS += min(UF.answer(AID), UF.answer(AID+M));
        }
    }
    rep(i,0,M) {
        if (UF.same(i,i+M)) return -1;
    }
    return ANS;
}

int main() {
while(1) {
    int N;
    cin >> N;
    if (N == 0) return 0;
    cout << Solve(N) << endl;
}
}
accuracy: 1
time_ms: 200
memory_kb: 3836
final_rank: 1