#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <unordered_map>
#include <deque>
#include <bits/extc++.h>
#include <ctime>
#include <cstdlib>
#include <random>
using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;
const int N = 1e6 + 5;
mt19937 rd(114);
struct Node
{
deque<int> q;
gp_hash_table<int, int> mp;
}p[N];
int n, m, rp[N];
int main()
{
//freopen("major4.in", "r", stdin);
// freopen("1.out", "w", stdout);
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
{
int cnt;
scanf("%d", &cnt);
while (cnt--)
{
int x;
scanf("%d", &x);
p[i].q.push_back(x);
p[i].mp[x]++;
}
}
for (int i = 0; i < N; i++) rp[i] = i;
while (m--)
{
int op;
scanf("%d", &op);
if (op == 1)
{
int x, y;
scanf("%d%d", &x, &y);
x = rp[x];
p[x].q.push_back(y);
p[x].mp[y]++;
}
else if (op == 2)
{
int x;
scanf("%d", &x);
x = rp[x];
p[x].mp[p[x].q.back()]--;
p[x].q.pop_back();
}
else if (op == 3)
{
int x;
scanf("%d", &x);
vector<int> pe;
int sum = 0;
for (int i = 1; i <= x; i++)
{
int g;
scanf("%d", &g);
g = rp[g];
sum += p[g].q.size();
pe.push_back(g);
}
bool f = false;
for (int i = 1; i <= 34; i++)
{
int c1 = rd() % x;
if (p[pe[c1]].q.empty()) continue;
int c2 = *(((rd() % p[pe[c1]].q.size()) + p[pe[c1]].q.begin()));
int sp = 0;
for (int j = 0; j < x; j++) sp += p[pe[j]].mp[c2];
if (sp > sum / 2)
{
f = true;
printf("%d\n", c2);
break;
}
}
if (!f) printf("-1\n");
}
else
{
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
x = rp[x], y = rp[y];
if (p[y].q.size() < p[x].q.size())
{
for (auto i : p[y].q)
{
p[x].q.push_back(i);
p[x].mp[i]++;
}
p[y].q.clear(), p[y].q.shrink_to_fit();
rp[z] = x;
}
else
{
while (p[x].q.size())
{
int i = p[x].q.back();
p[x].q.pop_back();
p[y].q.push_front(i);
p[y].mp[i]++;
}
p[x].q.shrink_to_fit();
rp[z] = y;
}
}
}
return 0;
}
启发式合并+deque,后面四个点t了,感觉复杂度没假吧,大样例很快啊