#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';
    }
}