#include "bits/stdc++.h"
using namespace std;
#define all(x) begin(x),end(x)
template<typename A, typename B> ostream& operator<<(ostream &os, const pair<A, B> &p) { return os << '(' << p.first << ", " << p.second << ')'; }
template<typename T_container, typename T = typename enable_if<!is_same<T_container, string>::value, typename T_container::value_type>::type> ostream& operator<<(ostream &os, const T_container &v) { string sep; for (const T &x : v) os << sep << x, sep = " "; return os; }
#define debug(a) cerr << "(" << #a << ": " << a << ")\n";
typedef long long ll;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef pair<int,int> pi;
const int mxN = 6e6+1, mxM = 1.1e5+10, oo = 1e9;
// mxN is maximum number of persistent treap nodes
const ll MOD = 1e9+7;
struct Node;
int size(Node* a);
struct Node{
// Persistent (functional) treap node, doesn't get changed after creation
array<Node*,2> kids = {};
int sz,data;
Node(int _data) {
data=_data;
sz = 1;
}
Node() {}
int kth(int k, bool reverse) {
int toleft = size(kids[reverse]);
if(toleft==k) {
return data;
} else if(toleft>k) {
return kids[reverse]->kth(k,reverse);
} else {
return kids[!reverse]->kth(k-toleft-1, reverse);
}
}
void recalc() {
sz=1+size(kids[0])+size(kids[1]);
}
void print() {
if(kids[0]) kids[0]->print();
// cout << data << ' ';
if(kids[1]) kids[1]->print();
}
};
int size(Node* a) {
if(!a) return 0;
return a->sz;
}
Node nodes[mxN]; int p=0;
Node* newnode(Node* c) {
assert(p<mxN);
auto& n = nodes[p++];
n.data = c->data;
n.sz = c->sz;
n.kids = c->kids;
return &n;
}
Node* newnode(int val) {
assert(p<mxN);
auto& n = nodes[p++];
n = Node(val);
return &n;
}
array<Node*,2> split(Node* c, int lastinleft) {
// functional treap split
// doesn't change nodes and makes new nodes when it's needed
if(size(c->kids[0])>=lastinleft) {
if(c->kids[0]==NULL) {
return {NULL,c};
}
auto cc = newnode(c);
auto ans = split(c->kids[0],lastinleft);
cc->kids[0]=ans[1];
cc->recalc();
return {ans[0],cc};
} else {
if(c->kids[1]==NULL) {
return {c,NULL};
}
lastinleft-=size(c->kids[0])+1;
auto ans = split(c->kids[1], lastinleft);
auto cc = newnode(c);
cc->kids[1]=ans[0];
cc->recalc();
return {cc,ans[1]};
}
}
bool isroot(int a, int b) {
return (ll)rand() * (a + b) < (ll)a * RAND_MAX;
}
Node* merge(Node* a, Node* b) {
// functional treap merge, returns root of newly created tree
if(a==NULL) return b;
if(b==NULL) return a;
if(isroot(size(a), size(b))) {
auto aa = newnode(a);
aa->kids[1] = merge(a->kids[1],b);
aa->recalc();
return aa;
} else {
auto bb = newnode(b);
bb->kids[0] = merge(a,b->kids[0]);
bb->recalc();
return bb;
}
}
struct listroot {
Node* left=NULL, *right=NULL;
// left and right persistent treaps that contain the head and tail part of this list
ll sum=0; // sum of current list
bool onetreap=true;
// if list size is less than 2*mxM, the entire list is stored in one treap
listroot() {}
listroot(int val) {
left = newnode(val);
sum = val;
}
};
listroot roots[int(4e5+60)] = {}; int rp=0;
void head(int i) {
auto& c = roots[i];
auto tup = split(c.left,1);
int val = tup[0]->data;
roots[rp++] = listroot(val);
auto& nxt = roots[rp++] = c;
nxt.left = tup[1];
nxt.sum = (MOD+c.sum-val);
while(nxt.sum>=MOD) nxt.sum-=MOD;
}
void tail(int i) {
auto& c = roots[i];
auto& nxt = roots[rp++] = c;
array<Node*,2> tup;
if(c.onetreap) {
tup = split(c.left, size(c.left)-1);
nxt.left = tup[0];
} else {
tup = split(c.right, size(c.right)-1);
nxt.right = tup[0];
}
int val = tup[1]->data;
nxt.sum = (MOD+c.sum-val);
while(nxt.sum>=MOD) nxt.sum-=MOD;
roots[rp++] = listroot(val);
}
void mergelist(int i, int j) {
auto& l = roots[i], &r = roots[j];
auto& nxt = roots[rp++];
nxt.sum = l.sum+r.sum;
while(nxt.sum>=MOD) nxt.sum-=MOD;
nxt.onetreap = l.onetreap and r.onetreap;
if(!l.onetreap) nxt.left = l.left;
if(!r.onetreap) nxt.right = r.right;
if(l.onetreap and r.onetreap) {
// l and r only store one treap each
// merge their treaps
nxt.left = merge(l.left, r.left);
if(size(nxt.left)>=2*mxM) {
// if nxt's treap can be split into two treaps of size mxM, do this
nxt.onetreap= false;
auto tup = split(nxt.left, mxM);
nxt.left = tup[0];
nxt.right = split(tup[1], size(tup[1])-mxM)[1];
}
} else if(l.onetreap) {
nxt.left = split(merge(l.left, r.left), mxM)[0];
} else if(r.onetreap) {
nxt.right = merge(l.right, r.left);
nxt.right = split(nxt.right, size(nxt.right)-mxM)[1];
}
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n; cin >> n;
for(int i=0;i<n;++i) {
int cur; cin >> cur;
roots[rp++] = listroot(cur);
}
int m; cin >> m;
for(int ops=0;ops<m;++ops) {
string op; cin >> op;
if(op == "merge") {
int i,j; cin >> i >> j;
--i,--j;
mergelist(i,j);
} else {
int i; cin >> i; --i;
if(op=="head") head(i);
else tail(i);
cout << roots[rp-2].sum << '\n';
}
cout << roots[rp-1].sum << '\n';
}
}