Problem:
Problem E: Distinct Dictionary
Background
辞書をこよなく愛する者がいた。彼らは自分だけの辞書を作ることが大好きである。
そこであなたは彼らの辞書に、自由にカスタマイズする機能を付け加えてあげることにした。
Problem
初めに、何の単語も入っていない空の辞書が存在する。
N
個の文字列
S
id
と
Q
個のクエリが与えられる。
各クエリはクエリの種類
k
と文字列を指す
id
で与えられる。
クエリの種類は以下の3つである。
k
=1のとき
S
id
を辞書に追加する。
k
=2のとき
S
id
を辞書から削除する。
k
=3のとき辞書に追加された文字列の中で
S
id
を先頭からの部分文字列に含み且つ辞書順最小の文字列の
id
を出力する。無い場合は-1を出力する。
各クエリに答えるプログラムを書いてほしい。
注意：
入力のサイズが大きいので高速な入力に対応する形式を推奨する。
Input
入力は以下の形式で与えられる。
N
S
1
S
2
.
.
.
S
N
Q
k
1
id
1
k
2
id
2
.
.
.
k
Q
id
Q
1行目に、1つの整数
N
が与えられる。2行目から
N
+1行に、
N
個の文字列
S
id
が与えられる。
N
+2行目にクエリの数
Q
が与えられ、続く
Q
行に各クエリの種類を表す
k
と文字列を指す
id
が与えれる。
Constraints
文字列は全て異なる。
N
個の文字列
S
id
の長さの合計は10
6
を超えない。
既に辞書に追加されている文字列が再び追加されるような入力は存在しない。
辞書に追加されていない文字列を削除するような入力は存在しない。
与えられる文字列に含まれる文字は英小文字のみである。
1 ≤
N
≤ 10
5
1 ≤
id
≤
N
1 ≤
Q
≤ 10
5
1 ≤ |
S
id
| ≤ 10
5
(ただし、|
s
|は文字列
s
の長さを表す。)
Output
クエリごとに解答を一行に出力せよ。
Sample Input1
3
apple
app
banana
9
1 1
3 1
3 2
3 3
2 1
1 2
3 1
3 2
3 3
Sample Output1
1
1
-1
-1
2
-1
Sample Input2
7
aaaab
aaa
aaaa
aaaaaabc
abbbbbc
ab
abbb
13
1 1
3 2
1 4
3 2
1 3
3 2
2 3
3 3
1 5
1 7
3 6
2 5
3 6
Sample Output2
1
4
3
4
7
7

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;

namespace atcoder {

namespace internal {

// @param n `0 <= n`
// @return minimum non-negative `x` s.t. `n <= 2**x`
int ceil_pow2(int n) {
    int x = 0;
    while ((1U << x) < (unsigned int)(n)) x++;
    return x;
}

// @param n `1 <= n`
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
int bsf(unsigned int n) {
#ifdef _MSC_VER
    unsigned long index;
    _BitScanForward(&index, n);
    return index;
#else
    return __builtin_ctz(n);
#endif
}

}  // namespace internal

}  // namespace atcoder

namespace atcoder {

template <class S, S (*op)(S, S), S (*e)()> struct segtree {
  public:
    segtree() : segtree(0) {}
    explicit segtree(int n) : segtree(std::vector<S>(n, e())) {}
    explicit segtree(const std::vector<S>& v) : _n(int(v.size())) {
        log = internal::ceil_pow2(_n);
        size = 1 << log;
        d = std::vector<S>(2 * size, e());
        for (int i = 0; i < _n; i++) d[size + i] = v[i];
        for (int i = size - 1; i >= 1; i--) {
            update(i);
        }
    }

    void set(int p, S x) {
        assert(0 <= p && p < _n);
        p += size;
        d[p] = x;
        for (int i = 1; i <= log; i++) update(p >> i);
    }

    S get(int p) const {
        assert(0 <= p && p < _n);
        return d[p + size];
    }

    S prod(int l, int r) const {
        assert(0 <= l && l <= r && r <= _n);
        S sml = e(), smr = e();
        l += size;
        r += size;

        while (l < r) {
            if (l & 1) sml = op(sml, d[l++]);
            if (r & 1) smr = op(d[--r], smr);
            l >>= 1;
            r >>= 1;
        }
        return op(sml, smr);
    }

    S all_prod() const { return d[1]; }

    template <bool (*f)(S)> int max_right(int l) const {
        return max_right(l, [](S x) { return f(x); });
    }
    template <class F> int max_right(int l, F f) const {
        assert(0 <= l && l <= _n);
        assert(f(e()));
        if (l == _n) return _n;
        l += size;
        S sm = e();
        do {
            while (l % 2 == 0) l >>= 1;
            if (!f(op(sm, d[l]))) {
                while (l < size) {
                    l = (2 * l);
                    if (f(op(sm, d[l]))) {
                        sm = op(sm, d[l]);
                        l++;
                    }
                }
                return l - size;
            }
            sm = op(sm, d[l]);
            l++;
        } while ((l & -l) != l);
        return _n;
    }

    template <bool (*f)(S)> int min_left(int r) const {
        return min_left(r, [](S x) { return f(x); });
    }
    template <class F> int min_left(int r, F f) const {
        assert(0 <= r && r <= _n);
        assert(f(e()));
        if (r == 0) return 0;
        r += size;
        S sm = e();
        do {
            r--;
            while (r > 1 && (r % 2)) r >>= 1;
            if (!f(op(d[r], sm))) {
                while (r < size) {
                    r = (2 * r + 1);
                    if (f(op(d[r], sm))) {
                        sm = op(d[r], sm);
                        r--;
                    }
                }
                return r + 1 - size;
            }
            sm = op(d[r], sm);
        } while ((r & -r) != r);
        return 0;
    }

  private:
    int _n, size, log;
    std::vector<S> d;

    void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
};

}  // namespace atcoder

using namespace atcoder;

constexpr char newl = '\n';

// recommend { MOD:2^61-1, base:random }
struct RollingHash{
  using i128 = __int128_t;
  using ll = long long;
  ll base,mod;
  vector<ll> hash,cumulative_sum,inv;
  RollingHash(vector<ll> vals,ll B,ll MOD = (1LL<<61)-1){
    set_base(B);
    set_mod(MOD);
    build(vals);
  }
  RollingHash(string &s,ll B,ll MOD = (1LL<<61)-1){
    vector<ll> vals;
    for(char c:s) vals.emplace_back(c);
    set_base(B);
    set_mod(MOD);
    build(vals);
  }
	RollingHash(){}

	void init(string &s,ll B,ll MOD = (1LL<<61)-1){
    vector<ll> vals;
    for(char c:s) vals.emplace_back(c);
    set_base(B);
    set_mod(MOD);
    build(vals);
	}

  void set_base(ll B){ base=B; }
  void set_mod(ll MOD){ mod=MOD; }

  // mod multiprecation
  ll mod_mul(ll a,ll b){
    i128 res=a;
    res*=b;
    res=(res >> 61) + (res & mod);
    if(res >= mod) res-=mod;
    return (ll)res;
  }

  ll pow(ll a,i128 e){
    if(e==0) return 1;
    if(e%2==0){
      ll res=pow(a,e/2);
      return mod_mul(res,res);
    }
    return mod_mul(pow(a,e-1),a);
  }

  void build(vector<ll> vals){
    int n=vals.size();
    hash.assign(n,0);
    cumulative_sum.assign(n+1,0);
    inv.assign(n+1,0);
    i128 e=mod-2;
    inv[n]=pow(base,n*e);
    for(int i=n-1;i>=0;i--) inv[i]=mod_mul(inv[i+1],base);
    for(int i=0;i<n;i++) hash[i]=mod_mul(vals[i],pow(base,i));
    for(int i=0;i<n;i++) cumulative_sum[i+1]=(hash[i]+cumulative_sum[i])%mod;
  }

  // [l,r)
  long long find(int l,int r){
    ll res=cumulative_sum[r]-cumulative_sum[l];
    if(res<0) res+=mod;
    res=mod_mul(res,inv[l]);
    return (long long)res;
  }
};

template<typename T>
struct RandomGenerator {
  mt19937 mt;
  RandomGenerator() : mt(chrono::steady_clock::now().time_since_epoch().count()) {}

  // [a, b)
  T operator()(T a, T b) {
    uniform_int_distribution<T> dist(a, b - 1);
    return dist(mt);
  }

  // [0, b)
  T operator()(T b) { return (*this)(0,b); }
};



int op(int a,int b){
	return min(a,b);
}

int e(){
	return INT32_MAX/2;
}


int main(){
	cin.tie(nullptr);
	ios::sync_with_stdio(false);

	int n;
	cin>>n;
	vector<string> s(n);
	for(int i=0;i<n;i++){
		cin>>s[i];
	}

	auto sorted=s;
	sort(sorted.begin(),sorted.end());

	vector<pair<string,int>> sorted_pair(n);
	for(int i=0;i<n;i++){
		sorted_pair[i].first=s[i];
		sorted_pair[i].second=i;
	}

	sort(sorted_pair.begin(),sorted_pair.end());
	


	int q;
	cin>>q;
	vector<int> k(q),id(q);
	for(int i=0;i<q;i++){
		cin>>k[i]>>id[i];
	}

  RandomGenerator<ll> rand;
  const ll base=rand(2LL,(1LL<<61)-1-2);
	vector<RollingHash> hashs(n);
	for(int i=0;i<n;i++){
		hashs[i].init(sorted[i],base);
	}
	// ここでソート済みの文字列のハッシュ構築済み



	segtree<int,op,e> tree(vector<int>(n,e()));


	
	for(int i=0;i<q;i++){
		if(k[i]==1){
			int sorted_idx=lower_bound(sorted.begin(),sorted.end(),s[id[i]-1])-sorted.begin();
			tree.set(sorted_idx,sorted_idx);
			continue;
		}
		if(k[i]==2){
			int sorted_idx=lower_bound(sorted.begin(),sorted.end(),s[id[i]-1])-sorted.begin();
			tree.set(sorted_idx,e());
			continue;
		}

		// ここで欲しい文字列のインデックス取得をする
		int sorted_idx=lower_bound(sorted.begin(),sorted.end(),s[id[i]-1])-sorted.begin();
		int idx=tree.prod(sorted_idx,n);


		if(idx>=n){
			cout<<-1<<newl;
			continue;
		}

		// s[sorted_idx]がs[idx]に含まれているかを判定する
		int sz1=sorted[sorted_idx].size();
		int sz2=sorted[idx].size();
		if(sz1>sz2){
			cout<<-1<<newl;
			continue;
		}

		// 検索する文字列の長さ分判定する
		if(hashs[sorted_idx].find(0,sz1)==hashs[idx].find(0,sz1)){
			cout<<sorted_pair[idx].second+1<<newl;
		}else{
			cout<<-1<<newl;
		}
	}
}
accuracy: 1
time_ms: 1000
memory_kb: 52148
final_rank: 14

code_snippet: #include <iostream>
#include <set>
#include <map>
#include <string>
using namespace std;
using llong = long long;

llong n, q;
string s[100005];
llong com, id;

auto cmp = [&](int i, int j) {
    return s[i] < s[j];
};

set<int, decltype(cmp)> st(cmp);

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> s[i];
    }

    cin >> q;
    for (int i = 0; i < q; i++) {
        cin >> com >> id;

        switch (com) {
            case 1:
            st.insert(id);
            break;
            case 2:
            st.erase(id);
            break;
            case 3:
            auto itr = st.lower_bound(id);
            if (itr == st.end()) cout << -1 << '\n';
            else cout << *itr << '\n';
            break;
        }
    }
}
accuracy: 0.047619047619047616
time_ms: 20
memory_kb: 8336
final_rank: 17

code_snippet: #include <iostream>
#include <set>
#include <map>
#include <string>
using namespace std;
using llong = long long;

llong n, q;
string s[100005];
llong com, id;
set<string> st;
map<string, int> mp;

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> s[i];
        mp[s[i]] = i + 1;
    }

    cin >> q;
    for (int i = 0; i < q; i++) {
        cin >> com >> id;
        id--;

        switch (com) {
            case 1:
            st.insert(s[id]);
            break;
            case 2:
            st.erase(s[id]);
            break;
            case 3:
            auto itr = st.lower_bound(s[id]);
            if (itr == st.end()) cout << -1 << '\n';
            else cout << mp[*itr] << '\n';
            break;
        }
    }
}
accuracy: 0.047619047619047616
time_ms: 50
memory_kb: 13696
final_rank: 18

code_snippet: #include <bits/stdc++.h>
using namespace std;

// template {{{
#define  range(i, l, r) for (int i = (int)(l); i < (int)(r); (i) += 1)
#define rrange(i, l, r) for (int i = (int)(r) - 1; i >= (int)(l); (i) -= 1)

#define  whole(f, x, ...) ([&](decltype((x)) container) { return (f)(  begin(container),  end(container), ## __VA_ARGS__); })(x)
#define rwhole(f, x, ...) ([&](decltype((x)) container) { return (f)( rbegin(container), rend(container), ## __VA_ARGS__); })(x)

#define debug(x) cerr << "(" << __LINE__ << ")" << #x << ": " << (x) << endl

using i32 = int;
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;

// constexpr i32 mod   = 998244353;
constexpr i32 mod   = 1e9 + 7;
constexpr i32 inf   = 1001001001;
constexpr i64 infll = 1001001001001001001ll;

constexpr int dx[] = {0, -1, 1, 0, -1, 1, -1, 1};
constexpr int dy[] = {-1, 0, 0, 1, -1, -1, 1, 1};

struct IoSetup { IoSetup(int x = 15){ cin.tie(0); ios::sync_with_stdio(0); cout << fixed << setprecision(x); cerr << fixed << setprecision(x); } } iosetup;

template <typename T = i64> T input() { T x; cin >> x; return x; }

template <typename T> ostream &operator<<(ostream &os, vector<T> &v) { range(i, 0, v.size()) { os << v[i] << (i + 1 != v.size() ? " " : ""); } return os; }
template <typename T> istream &operator>>(istream &is, vector<T> &v) { for (T &in : v) is >> in; return is; }

template <typename T1, typename T2> ostream &operator<<(ostream &os, pair<T1, T2> p) { os << "(" << p.first << ", " << p.second << ")"; return os; }
template <typename T1, typename T2> istream &operator>>(istream &is, pair<T1, T2> &p) { is >> p.first >> p.second; return is; }

template <typename T> vector<T> make_vector(size_t a, T b) { return vector<T>(a, b); }
template <typename... Ts> auto make_vector(size_t a, Ts... ts) { return vector<decltype(make_vector(ts...))>(a, make_vector(ts...)); }

template <typename T1, typename T2> inline bool chmax(T1 &a, T2 b) { return a < b && (a = b, true); }
template <typename T1, typename T2> inline bool chmin(T1 &a, T2 b) { return a > b && (a = b, true); }
// }}}

template< unsigned mod >
struct RollingHash {
    vector< unsigned > hashed, power;

    inline unsigned mul(unsigned a, unsigned b) const {
        unsigned long long x = (unsigned long long) a * b;
        unsigned xh = (unsigned) (x >> 32), xl = (unsigned) x, d, m;
        asm("divl %4; \n\t" : "=a" (d), "=d" (m) : "d" (xh), "a" (xl), "r" (mod));
        return m;
    }

    RollingHash(const string &s, unsigned base = 10007) {
        int sz = (int) s.size();
        hashed.assign(sz + 1, 0);
        power.assign(sz + 1, 0);
        power[0] = 1;
        for(int i = 0; i < sz; i++) {
            power[i + 1] = mul(power[i], base);
            hashed[i + 1] = mul(hashed[i], base) + s[i];
            if(hashed[i + 1] >= mod) hashed[i + 1] -= mod;
        }
    }

    unsigned get(int l, int r) const {
        unsigned ret = hashed[r] + mod - mul(hashed[l], power[r - l]);
        if(ret >= mod) ret -= mod;
        return ret;
    }

    unsigned connect(unsigned h1, int h2, int h2len) const {
        unsigned ret = mul(h1, power[h2len]) + h2;
        if(ret >= mod) ret -= mod;
        return ret;
    }

    int LCP(const RollingHash< mod > &b, int l1, int r1, int l2, int r2) {
        int len = min(r1 - l1, r2 - l2);
        int low = -1, high = len + 1;
        while(high - low > 1) {
            int mid = (low + high) / 2;
            if(get(l1, l1 + mid) == b.get(l2, l2 + mid)) low = mid;
            else high = mid;
        }
        return (low);
    }
};

using RH = RollingHash< 1000000007 >;

void solver() {
    int n;
    cin >> n;

    vector< string > ss(n);
    vector< pair< string, int > > ps(n);
    range(i, 0, n) {
        cin >> ss[i];
        ps[i] = make_pair(ss[i], i);
    }

    whole(sort, ps);

    vector< int > tos(n);
    range(i, 0, n) {
        tos[ps[i].second] = i;
    }

    vector< RH > rs;
    range(i, 0, n) {
        rs.emplace_back(RH(ps[i].first));
    }


    set< int > st;
    st.insert(n);
    int q = input();

    while (q--) {
        int k, id;
        cin >> k >> id;

        id = tos[id - 1];

        if (k == 1) {
            st.insert(id);
        }

        if (k == 2) {
            st.erase(id);
        }

        if (k == 3) {
            int idx = *st.lower_bound(id);
            
            if (idx == n) {
                cout << -1 << endl;
                continue;
            }

            int r = ps[id].first.size();
            if (rs[idx].hashed.size() >= rs[id].hashed.size() && 
                rs[idx].get(0, r) == rs[id].get(0, r)) {
                cout << ps[idx].second + 1 << endl;
            } else {
                cout << -1 << endl;
            }
        }
    }
}

signed main(int argc, char *argv[]) {
    solver();
}
accuracy: 1
time_ms: 120
memory_kb: 29176
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;
struct segment_tree{
  int N;
  vector<int> ST;
  segment_tree(int n){
    N = 1;
    while (N < n){
      N *= 2;
    }
    ST = vector<int>(N * 2 - 1, 0);
  }
  void update(int i, int x){
    i += N - 1;
    ST[i] = x;
    while (i > 0){
      i = (i - 1) / 2;
      ST[i] = ST[i * 2 + 1] + ST[i * 2 + 2];
    }
  }
  int query(int L, int R, int i, int l, int r){
    if (r <= L || R <= l){
      return 0;
    } else if (L <= l && r <= R){
      return ST[i];
    } else {
      int m = (l + r) / 2;
      return query(L, R, i * 2 + 1, l, m) + query(L, R, i * 2 + 2, m, r);
    }
  }
  int query(int L, int R){
    return query(L, R, 0, 0, N);
  }
};
int main(){
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  int N;
  cin >> N;
  vector<pair<string, int>> S(N);
  for (int i = 0; i < N; i++){
    cin >> S[i].first;
    S[i].second = i + 1;
  }
  sort(S.begin(), S.end());
  //id -> pos
  vector<int> pos(N + 1, -1);
  for (int i = 0; i < N; i++){
    pos[S[i].second] = i;
  }
  //string -> position
  map<string, int> mp;
  for (int i = 0; i < N; i++){
    mp[S[i].first] = i;
  }
  //Find range
  vector<int> R(N);
  for (int i = 0; i < N; i++){
    string T = S[i].first;
    T.back()++;
    auto itr = mp.lower_bound(T);
    itr--;
    R[i] = (*itr).second + 1;
  }
  //debug
  /*
  for (int i = 0; i < N; i++){
    cout << R[i] << endl;
  }
  */
  //point update range sum
  segment_tree ST(N);
  //queries
  int Q;
  cin >> Q;
  for (int i = 0; i < Q; i++){
    int k, id;
    cin >> k >> id;
    int p = pos[id];
    //cout << "pos = " << p << endl;
    if (k == 1){
      ST.update(p, 1);
    }
    if (k == 2){
      ST.update(p, 0);
    }
    if (k == 3){
      if (ST.query(p, R[p]) == 0){
        cout << -1 << endl;
      } else {
        //binary search
        int tv = R[p];
        int fv = p - 1;
        while (tv - fv > 1){
          int mv = (tv + fv) / 2;
          if (ST.query(p, mv) != 0){
            tv = mv;
          } else {
            fv = mv;
          }
        }
        cout << S[fv].second << endl;
      }
    }
  }
}
accuracy: 1
time_ms: 130
memory_kb: 17164
final_rank: 3

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define SIZE 100005

struct Data{

	bool operator<(const struct Data &arg) const{

		return line < arg.line;
	}
	int index;
	string line;
};

struct Node{
	int children[26];
	bool finish_FLG;
};


int N;
int length[SIZE];
int L[SIZE],R[SIZE];
int num_node;
map<int,int> MAP,rev_MAP,TAIL;
set<int> SET;
Data data[SIZE];
Node nodes[1000005];

int main(){

	scanf("%d",&N);

	for(int i = 0; i < N; i++){

		cin >> data[i].line;
		data[i].index = i;
		length[i] = data[i].line.length();
	}

	sort(data,data+N);

	for(int i = 0; i < N; i++){

		MAP[data[i].index] = i; //文字列がdataのどこにあるか
		rev_MAP[i] = data[i].index; //dataのi番目の文字列は何か

		L[i] = BIG_NUM; //自分を含む最小のindex
		R[i] = -BIG_NUM; //自分を含む細大のindex
	}

	num_node = 0;

	for(int i = 0; i < 1000005; i++){

		for(int k = 0; k < 26; k++){

			nodes[i].children[k] = -1;
		}
		nodes[i].finish_FLG = false;
	}

	int root = 0;

	for(int i = 0; i < N; i++){

		int tmp_index = 0; //文字列のインデックス
		int tmp_ch = data[i].line[tmp_index]-'a';

		int tmp_loc = root; //トライ木上の位置
		tmp_index = 0;

		while(true){

			if(nodes[tmp_loc].finish_FLG){ //終端する文字列あり

				int k = TAIL[tmp_loc];
				R[k] = i;
			}

			if(nodes[tmp_loc].children[tmp_ch] == -1){

				nodes[tmp_loc].children[tmp_ch] = ++num_node;
			}
			//子ノードに移動
			tmp_loc = nodes[tmp_loc].children[tmp_ch];
			tmp_index++;

			if(tmp_index == length[rev_MAP[i]]){ //今回の数字が最後の文字だった場合
				nodes[tmp_loc].finish_FLG = true;
				TAIL[tmp_loc] = rev_MAP[i];
				L[rev_MAP[i]] = i;
				R[rev_MAP[i]] = i;
				break;
			}
			tmp_ch = data[i].line[tmp_index]-'a';
		}
	}

	int num_query;
	scanf("%d",&num_query);

	int command,num;

	set<int>::iterator it;

	for(int loop = 0; loop < num_query; loop++){

		scanf("%d %d",&command,&num);
		num--;

		switch(command){
		case 1:

			SET.insert(MAP[num]);
			break;

		case 2:

			SET.erase(MAP[num]);
			break;

		case 3:

			if(L[num] == BIG_NUM){ //元々自分を含む文字列なし

				printf("-1\n");
				break;
			}

			it = SET.lower_bound(L[num]);

			if (it == SET.end() || *it > R[num]){

				printf("-1\n");

			}else{

				printf("%d\n", rev_MAP[*it]+1);
			}
			break;
		}
	}

	return 0;
}
accuracy: 1
time_ms: 300
memory_kb: 133356
final_rank: 13

code_snippet: #include <bits/stdc++.h>
#define MOD 1000000007LL
using namespace std;
typedef long long ll;
typedef pair<string,int> P;

struct rollinghash{
	static const int MD=3;
	const ll base[MD]={1007LL,1009LL,1009LL};
	const ll mods[MD]={999999937LL, 1000000007LL,912941443LL};
	vector<ll> hash[MD];
	vector<ll> pw[MD];
	void construct(const string &str){
		int n=str.size();
		for(int i=0;i<MD;i++){
			pw[i].resize(n+1);
			pw[i][0]=1;
			for(int j=0;j<n;j++){
				pw[i][j+1]=pw[i][j]*base[i]%mods[i];
			}
		}
		for(int i=0;i<MD;i++){
			hash[i].resize(n+1);
			hash[i][0]=0;
			for(int j=0;j<n;j++){
				hash[i][j+1]=(hash[i][j]*base[i]%mods[i]+str[j])%mods[i];
			}
		}
	}

	// calc hash value [l,r)
	ll hash_value(int l,int r,int i){
		return ((hash[i][r]-hash[i][l]*pw[i][r-l])%mods[i]+mods[i])%mods[i];
	}
};

rollinghash rol[100005];

int n;
const int B=300;
P p[100005];
int rid[100005];
int cnt[100005];
int Bcnt[500];

bool isok(int s,int t){
	//printf("isok%d %d\n",s,t);
	int len=p[s].first.size();
	for(int i=0;i<3;i++){
		if(rol[s].hash_value(0,len,i)!=rol[t].hash_value(0,len,i))return false;
	}
	return true;
}

int query(int s){
	int v=s;
	while(v%B!=0 && v<n){
		if(cnt[v]==1){
			if(p[s].first.size()>p[v].first.size())return -1;
			if(isok(s,v)){
				return (p[v].second+1);
			}else{
				return -1;
			}
		}
		v++;
	}
	while(v<n){
		if(Bcnt[v/B]>0)break;
		v+=B;
	}
	while(v<n){
		if(cnt[v]==1){
			if(p[s].first.size()>p[v].first.size())return -1;
			if(isok(s,v)){
				return (p[v].second+1);
			}else{
				return -1;
			}
		}
		v++;
	}
	return -1;
}

int main(void){
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		cin >> p[i].first;
		p[i].second=i;
	}
	sort(p,p+n);
	for(int i=0;i<n;i++){
		rol[i].construct(p[i].first);
		rid[p[i].second]=i;
	}
	int q;
	scanf("%d",&q);
	for(int i=0;i<q;i++){
		int a,b;
		scanf("%d%d",&a,&b);
		b--;
		if(a==1){
			cnt[rid[b]]++;
			Bcnt[rid[b]/B]++;
		}
		if(a==2){
			cnt[rid[b]]--;
			Bcnt[rid[b]/B]--;
		}
		if(a==3){
			printf("%d\n",query(rid[b]));
		}
	}
	return 0;
}
accuracy: 1
time_ms: 240
memory_kb: 86908
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout<<#x" = "<<((x))<<endl
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}

struct RollingHash{
    static const int MD = 2;
    static const vector<ll> hash_base, hash_mod;

    int n;
    vector<ll> hs[MD], pw[MD];

    RollingHash(){}
    RollingHash(const string &s){
        n = s.size();
        rep(i,MD){
            hs[i].assign(n+1,0);
            pw[i].assign(n+1,0);
            hs[i][0] = 0;
            pw[i][0] = 1;
            rep(j,n){
                pw[i][j+1] = pw[i][j]*hash_base[i] % hash_mod[i];
                hs[i][j+1] = (hs[i][j]*hash_base[i]+s[j]) % hash_mod[i];
            }
        }
    }

    // 1-index
    ll hash_value(int l, int r, int i){
        return ((hs[i][r] - hs[i][l]*pw[i][r-l])%hash_mod[i]+hash_mod[i])%hash_mod[i];
    }

    bool match(int l1, int r1, int l2, int r2){
        bool ret = true;
        rep(i,MD) ret &= (hash_value(l1-1,r1,i) == hash_value(l2-1,r2,i));
        return ret;
    }

    ll calc(int l, int r){
        ll ret = 0;
        rep(i,MD) ret |= (hash_value(l-1,r,i)<<(i*32));
        return ret;
    }
};
const vector<ll> RollingHash::hash_base{1009,1021};
const vector<ll> RollingHash::hash_mod{1000000009,1000000007};



using P = pair<string,int>;

int main(){
    int n;
    scanf(" %d", &n);

    vector<P> s(n);
    rep(i,n){
        char tt[100010];
        scanf(" %s", tt);
        s[i] = {string(tt), i};
    }

    sort(all(s));

    vector<int> f(n),sz(n);
    rep(i,n){
        f[s[i].se] = i;
        sz[i] = s[i].fi.size();
    }

    vector<RollingHash> h(n);
    rep(i,n) h[i] = RollingHash(s[i].fi);

    auto check = [&](int a, int b){
        if(sz[a] > sz[b]) return false;

        ll va = h[a].calc(1,sz[a]);
        ll vb = h[b].calc(1,sz[a]);
        return va == vb;
    };

    set<int> active;
    int Q;
    scanf(" %d", &Q);
    while(Q--){
        int k,id;
        scanf(" %d %d", &k, &id);
        --id;

        if(k == 1) active.insert(f[id]);
        else if(k == 2) active.erase(f[id]);
        else{
            int ans = -1;
            auto itr = active.lower_bound(f[id]);
            if(itr != active.end()){
                int idx = *itr;
                if(check(f[id], idx)) ans = s[idx].se+1;
            }
            printf("%d\n", ans);
        }
    }

    return 0;
}
accuracy: 1
time_ms: 130
memory_kb: 59236
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;

typedef pair<int,int> P;
typedef long long ll;

#define repl(i,a,b) for(int i=(int)(a);i<(int)(b);(i)++)
#define rep(i,n) repl(i,0,n)
#define dbg(x) cout<<#x<<"="<<x<<endl

#define INF INT_MAX/3

struct RangeMinQuery{
  int dat[(1<<19)-1];
  int size;

  void init(int n_){
    size=1;
    while(size<n_)size*=2;
    for(int i=0;i<2*size-1;i++)dat[i]=INF;
  }

  void update(int k,int a){
    k+=size-1;
    dat[k]=a;
    while(k>0){
      k=(k-1)/2;
      dat[k]=min(dat[k*2+1],dat[k*2+2]);
    }
  }

  int subquery(int a,int b,int k,int l,int r){
    if(r<=a||b<=l)return INF;
    if(a<=l&&r<=b)return dat[k];
    else{
      return min(subquery(a,b,k*2+1,l,(l+r)/2),subquery(a,b,k*2+2,(l+r)/2,r));
    }
  }

  int query(int a,int b){
    return subquery(a,b,0,0,size);
  }
};

struct BIT{
  int n;
  vector<int> bit;
  BIT(int size):n(size),bit(size+1,0){}

  int sum(int i){
    int s=0;
    while(i>0){
      s+=bit[i];
      i-=i&-i;
    }
    return s;
  }

  void add(int i,int v){
    if(i==0)return ;
    while(i<=n){
      bit[i]+=v;
      i+=i&-i;
    }
  }

  int lower_bound(int w){
    if(w<=0)return 0;
    int x=0,r=1;
    while(r<n)r<<=1;
    for(int k=r;k>0;k>>=1){
      if(x+k<=n&&bit[x+k]<w){
        w-=bit[x+k];
        x+=k;
      }
    }
    return x+1;
  }
};

int N,Q;
char input[1000010];
vector<string> S;
vector<int> ord;
int ridx[100010],lcp[100010];
RangeMinQuery rmq;

int main(){
  scanf("%d",&N);
  S.resize(N);
  rep(i,N){
    scanf("%s",input);
    S[i]=string(input);
    ord.push_back(i);
  }
  sort(ord.begin(),ord.end(),[=](const int& a,const int& b){
    return S[a] < S[b];
  });
  rep(i,N){
    ridx[ord[i]]=i;
  }
  rmq.init(N-1);
  rep(i,N-1){
    lcp[i]=0;
    rep(j,min(S[ord[i]].size(),S[ord[i+1]].size())){
      if(S[ord[i]][j]==S[ord[i+1]][j])lcp[i]++;
      else break;
    }
    // dbg(lcp[i]);
    rmq.update(i,lcp[i]);
  }

  BIT bit(N);

  scanf("%d",&Q);
  rep(i,Q){
    int a,b;
    scanf("%d%d",&a,&b);
    a--; b--;
    if(a==0){
      bit.add(ridx[b]+1,+1);
    }else if(a==1){
      bit.add(ridx[b]+1,-1);
    }else{
      int sum=bit.sum(ridx[b]);
      int idx=bit.lower_bound(sum+1);
      if(idx==N+1){
        cout<<-1<<endl;
        continue;
      }
      int len=rmq.query(ridx[b],idx-1);
      if(len>=(int)S[b].size())cout<<ord[idx-1]+1<<endl;
      else cout<<-1<<endl;
    }
  }

  return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 11112
final_rank: 2

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

using namespace std;

using int64 = long long;
const int mod = 1e9 + 7;
const int inf = (1 << 30) - 1;
const int64 infll = (1LL << 61) - 1;

struct IoSetup {
  IoSetup() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);
    cerr << fixed << setprecision(10);
  }
} iosetup;

template< typename T >
ostream &operator<<(ostream &os, const vector< T > &v) {
  for(int i = 0; i < (int) v.size(); i++) {
    os << v[i] << (i + 1 != v.size() ? " " : "");
  }
  return os;
}

template< typename T >
istream &operator>>(istream &is, vector< T > &v) {
  for(T &in : v) is >> in;
  return is;
}

template< typename T1, typename T2 >
inline bool chmax(T1 &a, T2 b) { return a < b && (a = b, true); }

template< typename T1, typename T2 >
inline bool chmin(T1 &a, T2 b) { return a > b && (a = b, true); }

template< typename T = int64 >
vector< T > make_v(size_t a) {
  return vector< T >(a);
}

template< typename T, typename... Ts >
auto make_v(size_t a, Ts... ts) {
  return vector< decltype(make_v< T >(ts...)) >(a, make_v< T >(ts...));
}

template< typename T, typename V >
typename enable_if< is_class< T >::value == 0 >::type fill_v(T &t, const V &v) {
  t = v;
}

template< typename T, typename V >
typename enable_if< is_class< T >::value != 0 >::type fill_v(T &t, const V &v) {
  for(auto &e : t) fill_v(e, v);
}

template< typename G >
struct HeavyLightDecomposition {
  G &g;
  vector< int > sz, in, out, head, rev, par;

  HeavyLightDecomposition(G &g) :
      g(g), sz(g.size()), in(g.size()), out(g.size()), head(g.size()), rev(g.size()), par(g.size()) {}

  void dfs_sz(int idx, int p) {
    par[idx] = p;
    sz[idx] = 1;
    if(g[idx].size() && g[idx][0] == p) swap(g[idx][0], g[idx].back());
    for(auto &to : g[idx]) {
      if(to == p) continue;
      dfs_sz(to, idx);
      sz[idx] += sz[to];
      if(sz[g[idx][0]] < sz[to]) swap(g[idx][0], to);
    }
  }

  void dfs_hld(int idx, int par, int &times) {
    in[idx] = times++;
    rev[in[idx]] = idx;
    for(auto &to : g[idx]) {
      if(to == par) continue;
      head[to] = (g[idx][0] == to ? head[idx] : to);
      dfs_hld(to, idx, times);
    }
    out[idx] = times;
  }

  void build() {
    dfs_sz(0, -1);
    int t = 0;
    dfs_hld(0, -1, t);
  }

  int la(int v, int k) {
    while(1) {
      int u = head[v];
      if(in[v] - k >= in[u]) return rev[in[v] - k];
      k -= in[v] - in[u] + 1;
      v = par[u];
    }
  }

  int lca(int u, int v) {
    for(;; v = par[head[v]]) {
      if(in[u] > in[v]) swap(u, v);
      if(head[u] == head[v]) return u;
    }
  }

  template< typename T, typename Q, typename F >
  T query(int u, int v, const T &ti, const Q &q, const F &f, bool edge = false) {
    T l = ti, r = ti;
    for(;; v = par[head[v]]) {
      if(in[u] > in[v]) swap(u, v), swap(l, r);
      if(head[u] == head[v]) break;
      l = f(q(in[head[v]], in[v] + 1), l);
    }
    return f(f(q(in[u] + edge, in[v] + 1), l), r);
//  return {f(q(in[u] + edge, in[v] + 1), l), r};
  }

  template< typename Q >
  void add(int u, int v, const Q &q, bool edge = false) {
    for(;; v = par[head[v]]) {
      if(in[u] > in[v]) swap(u, v);
      if(head[u] == head[v]) break;
      q(in[head[v]], in[v] + 1);
    }
    q(in[u] + edge, in[v] + 1);
  }
};

template< int char_size >
struct TrieNode {
  int nxt[char_size + 1];

  int exist; // 子ども以下に存在する文字列の数の合計
  vector< int > accept; // その文字列id

  TrieNode() : exist(0) {
    memset(nxt, -1, sizeof(nxt));
  }
};

template< int char_size, int margin >
struct Trie {
  using Node = TrieNode< char_size >;

  vector< Node > nodes;
  int root;

  Trie() : root(0) {
    nodes.push_back(Node());
  }

  virtual void direct_action(int node, int id) {}

  virtual void child_action(int node, int child, int id) {}

  void update_direct(int node, int id) {
    nodes[node].accept.push_back(id);
    direct_action(node, id);
  }

  void update_child(int node, int child, int id) {
    ++nodes[node].exist;
    child_action(node, child, id);
  }

  void add(const string &str, int str_index, int node_index, int id) {
    if(str_index == str.size()) {
      update_direct(node_index, id);
    } else {
      const int c = str[str_index] - margin;
      if(nodes[node_index].nxt[c] == -1) {
        nodes[node_index].nxt[c] = (int) nodes.size();
        nodes.push_back(Node());
      }
      add(str, str_index + 1, nodes[node_index].nxt[c], id);
      update_child(node_index, nodes[node_index].nxt[c], id);
    }
  }

  void add(const string &str, int id) {
    add(str, 0, 0, id);
  }

  void add(const string &str) {
    add(str, nodes[0].exist);
  }

  void query(const string &str, const function< void(int) > &f, int str_index, int node_index) {
    for(auto &idx : nodes[node_index].accept) f(idx);
    if(str_index == str.size()) {
      return;
    } else {
      const int c = str[str_index] - margin;
      if(nodes[node_index].nxt[c] == -1) return;
      query(str, f, str_index + 1, nodes[node_index].nxt[c]);
    }
  }

  void query(const string &str, const function< void(int) > &f) {
    query(str, f, 0, 0);
  }

  int size() const {
    return (nodes[0].exist);
  }

  int nodesize() const {
    return ((int) nodes.size());
  }

};

template< typename T >
struct edge {
  int src, to;
  T cost;

  edge(int to, T cost) : src(-1), to(to), cost(cost) {}

  edge(int src, int to, T cost) : src(src), to(to), cost(cost) {}

  edge &operator=(const int &x) {
    to = x;
    return *this;
  }

  operator int() const { return to; }
};

template< typename T >
using Edges = vector< edge< T > >;
template< typename T >
using WeightedGraph = vector< Edges< T > >;
using UnWeightedGraph = vector< vector< int > >;
template< typename T >
using Matrix = vector< vector< T > >;

template< typename Monoid >
struct SegmentTree {
  using F = function< Monoid(Monoid, Monoid) >;

  int sz;
  vector< Monoid > seg;

  const F f;
  const Monoid M1;

  SegmentTree(int n, const F f, const Monoid &M1) : f(f), M1(M1) {
    sz = 1;
    while(sz < n) sz <<= 1;
    seg.assign(2 * sz, M1);
  }

  void set(int k, const Monoid &x) {
    seg[k + sz] = x;
  }

  void build() {
    for(int k = sz - 1; k > 0; k--) {
      seg[k] = f(seg[2 * k + 0], seg[2 * k + 1]);
    }
  }

  void update(int k, const Monoid &x) {
    k += sz;
    seg[k] = x;
    while(k >>= 1) {
      seg[k] = f(seg[2 * k + 0], seg[2 * k + 1]);
    }
  }

  Monoid query(int a, int b) {
    Monoid L = M1, R = M1;
    for(a += sz, b += sz; a < b; a >>= 1, b >>= 1) {
      if(a & 1) L = f(L, seg[a++]);
      if(b & 1) R = f(seg[--b], R);
    }
    return f(L, R);
  }

  Monoid operator[](const int &k) const {
    return seg[k + sz];
  }
};


int main() {
  int N;
  cin >> N;
  vector< string > S(N);
  cin >> S;
  Trie< 26, 'a' > trie;
  vector< int > ord(N);
  iota(begin(ord), end(ord), 0);
  sort(begin(ord), end(ord), [&](int a, int b) {
    return S[a] < S[b];
  });
  vector< int > rev(N);
  for(int i = 0; i < N; i++) rev[ord[i]] = i;
  for(int i = 0; i < S.size(); i++) trie.add(S[ord[i]], i);
  UnWeightedGraph g(trie.nodesize());
  vector< int > id(N);
  function< void(int) > dfs = [&](int idx) {
    for(auto i : trie.nodes[idx].accept) id[i] = idx;
    for(int i = 0; i < 26; i++) {
      if(~trie.nodes[idx].nxt[i]) {
        g[idx].emplace_back(trie.nodes[idx].nxt[i]);
        dfs(trie.nodes[idx].nxt[i]);
      }
    }
  };
  dfs(0);
  HeavyLightDecomposition< UnWeightedGraph > hld(g);
  hld.build();
  int Q;
  cin >> Q;
  auto f = [](int a, int b) { return min(a, b); };
  SegmentTree< int > seg(g.size(), f, inf);
  auto q = [&](int a, int b) { return seg.query(a, b); };
  while(Q--) {
    int a, b;
    cin >> a >> b;
    --b;
    if(a == 1) {
      seg.update(hld.in[id[rev[b]]], rev[b]);
    } else if(a == 2) {
      seg.update(hld.in[id[rev[b]]], inf);
    } else {
      auto ret = seg.query(hld.in[id[rev[b]]], hld.out[id[rev[b]]]);
      if(ret == inf) cout << -1 << endl;
      else cout << ord[ret] + 1 << endl;
    }
  }
}
accuracy: 1
time_ms: 280
memory_kb: 220940
final_rank: 15

code_snippet: #include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <set>
#include <utility>
using namespace std;

typedef unsigned long long ull;

// BASE: 29,53,131,257
// MOD: 636094623231363827,348051774975651917,140814840257324803,71777214294589669

int main() {
  ios::sync_with_stdio(false);
  int N; cin >> N;
  vector<pair<string, int>> S(N);
  for(int i = 0; i < N; ++i) {
    cin >> S[i].first;
    S[i].second = i;
  }
  sort(S.begin(), S.end());
  vector<int> M(N);
  for(int i = 0; i < N; ++i) {
    M[S[i].second] = i;
  }
  vector<vector<ull>> hash(N);
  for(int i = 0; i < N; ++i) {
    ull h = 0ULL;
    for(int j = 0; j < (int)S[i].first.length(); ++j) {
      h *= 29;
      h += (S[i].first[j] - 'a');
      h %= 636094623231363827;
      hash[i].push_back(h);
    }
  }
  set<int> D;
  int Q; cin >> Q;
  for(int q = 0; q < Q; ++q) {
    int k, id; cin >> k >> id;
    --id;
    if(k == 1) {
      D.insert(M[id]);
    }
    else if(k == 2) {
      D.erase(M[id]);
    }
    else {
      bool ok = false;
      auto succ = D.lower_bound(M[id]);
      if(succ != D.end() && S[M[id]].first.size() <= S[*succ].first.size() && hash[M[id]][S[M[id]].first.size() - 1] == hash[*succ][S[M[id]].first.size() - 1]) ok = true;
      if(ok) {
        cout << S[*succ].second + 1 << endl;
      }
      else {
        cout << -1 << endl;
      }
    }
  }
}
accuracy: 1
time_ms: 150
memory_kb: 25744
final_rank: 5

code_snippet: #include <cstdio>
#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <bitset>
#include <numeric>
#include <limits>
#include <climits>
#include <cfloat>
#include <functional>
using namespace std;

int main()
{
    int n;
    cin >> n;
    vector<pair<string, int> > s(n);
    vector<int> longStr;
    for(int i=0; i<n; ++i){
        cin >> s[i].first;
        if(s[i].first.size() >= 1000)
            longStr.push_back(i);
        s[i].second = i + 1;
    }
    sort(s.begin(), s.end());

    vector<int> index(n+1);
    for(int i=0; i<n; ++i)
        index[s[i].second] = i;

    map<pair<int, int>, bool> compLongStr;
    for(int x : longStr){
        for(int y : longStr){
            compLongStr[make_pair(x, y)] = (s[y].first.substr(0, s[x].first.size()) == s[x].first);
        }
    }

    int q;
    cin >> q;
    set<int> dic;
    while(--q >= 0){
        int k, x;
        cin >> k >> x;
        x = index[x];

        if(k == 1){
            dic.insert(x);
        }
        else if(k == 2){
            dic.erase(x);
        }
        else{
            auto it = dic.lower_bound(x);
            if(it == dic.end()){
                cout << -1 << endl;
                continue;
            }

            int y = *it;
            if(compLongStr.find(make_pair(x, y)) != compLongStr.end()){
                if(compLongStr[make_pair(x, y)])
                    cout << s[y].second << endl;
                else
                    cout << -1 << endl;
            }
            else{
                if(s[y].first.substr(0, s[x].first.size()) == s[x].first)
                    cout << s[y].second << endl;
                else
                    cout << -1 << endl;
            }
        }
    }

    return 0;
}
accuracy: 1
time_ms: 210
memory_kb: 12912
final_rank: 6

code_snippet: #include <cstdio>
#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <bitset>
#include <numeric>
#include <limits>
#include <climits>
#include <cfloat>
#include <functional>
using namespace std;

int main()
{
    int n;
    cin >> n;
    vector<pair<string, int> > s(n);
    vector<int> longStr;
    for(int i=0; i<n; ++i){
        cin >> s[i].first;
        if(s[i].first.size() >= 1000)
            longStr.push_back(i);
        s[i].second = i + 1;
    }
    sort(s.begin(), s.end());

    vector<int> index(n+1);
    for(int i=0; i<n; ++i)
        index[s[i].second] = i;

    map<pair<int, int>, bool> compLongStr;
    for(int i : longStr){
        for(int j : longStr){
            compLongStr[make_pair(i, j)] = s[i].first <= s[j].first;
        }
    }

    int q;
    cin >> q;
    set<int> dic;
    while(--q >= 0){
        int k, x;
        cin >> k >> x;
        x = index[x];

        if(k == 1){
            dic.insert(x);
        }
        else if(k == 2){
            dic.erase(x);
        }
        else{
            auto it = dic.lower_bound(x);
            if(it == dic.end()){
                cout << -1 << endl;
                continue;
            }

            int y = *it;
            if(compLongStr.find(make_pair(x, y)) != compLongStr.end()){
                if(compLongStr[make_pair(x, y)])
                    cout << s[y].second << endl;
                else
                    cout << -1 << endl;
            }
            else{
                if(s[y].first.substr(0, s[x].first.size()) == s[x].first)
                    cout << s[y].second << endl;
                else
                    cout << -1 << endl;
            }
        }
    }

    return 0;
}
accuracy: 0.2857142857142857
time_ms: 200
memory_kb: 10500
final_rank: 16

code_snippet: #include<cstdio>
#include <iostream>
#include <algorithm>
#include<set>
using namespace std;

struct data{
  string s;
  int id, num;

  bool operator <(data d) const{
    if(d.s < s) return false;
    return true;
  }
};
int N;

typedef unsigned long long ull;

const ull B = 100000007;

bool contain(string a, string b){
  int al = a.length(), bl = b.length();
  if(al > bl) return false;
  
  ull t = 1;
  for(int i = 0 ; i < al ; i++) t *= B;
  
  ull ah = 0, bh = 0;
  for(int i = 0 ; i < al ; i++) ah = ah * B + a[i];
  for(int i = 0 ; i < al ; i++) bh = bh * B + b[i];
  
  if(ah == bh) return true;
  return false;

}

int main() {
  //cin >> N;
  scanf("%d", &N);
  data dict[N];
  int A[N];

  for(int i=0; i<N; i++){
    cin>>dict[i].s;
    dict[i].num=0;
    dict[i].id=i;
  }
  sort(dict, dict+N);
  //dictを辞書順sortする

  for(int i=0; i<N; i++){
    A[dict[i].id]=i;
  }
  
  set<int> S;
  
  int Q;
  cin >> Q;
  for(int i=0; i<Q; i++){
    int k, idx;
    //cin >> k >> idx;
    scanf("%d%d", &k, &idx);
    //cout<< dict[A[idx-1]].s<<endl;
    if(k==1){
      dict[A[idx-1]].num=1;
      S.insert(A[idx-1]);
    }
    else if(k==2){
      dict[A[idx-1]].num=0;
      S.erase(A[idx-1]);
    }
    else{
      int flag=0;
      set<int>::iterator j = S.lower_bound(A[idx-1]);
      //cout << "j = " << *j << endl;
      
      //for(int j=A[idx-1]; j<N; j++){
	if(dict[*j].num==1){
	  //部分文字列の判定
	  if(contain(dict[A[idx-1]].s, dict[*j].s)){
	    //cout<<dict[j].id+1<<endl;
	      printf("%d\n", dict[*j].id+1);
	      flag=1;
	    }
	    }
	if(j==S.end()){
	  //cout<<-1<<endl;
	  printf("-1\n");
	}
	}
    }
  return 0;
  
}
accuracy: 0.047619047619047616
time_ms: 110
memory_kb: 8772
final_rank: 19

code_snippet: #include <string>
#include <vector>
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<stack>
#include<queue>
#include<cmath>
#include<algorithm>
#include<functional>
#include<list>
#include<deque>
#include<bitset>
#include<set>
#include<map>
#include<unordered_map>
#include<cstring>
#include<sstream>
#include<complex>
#include<iomanip>
#include<numeric>
#define X first
#define Y second
#define pb push_back
#define rep(X,Y) for (int (X) = 0;(X) < (Y);++(X))
#define rrep(X,Y) for (int (X) = (Y-1);(X) >=0;--(X))
#define repe(X,Y) for ((X) = 0;(X) < (Y);++(X))
#define peat(X,Y) for (;(X) < (Y);++(X))
#define all(X) (X).begin(),(X).end()
#define rall(X) (X).rbegin(),(X).rend()

using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
//template<class T> using vv=vector<vector<T>>;
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"{"; rep(i,t.size()) {os<<t[i]<<",";} os<<"}"<<endl; return os;}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}

int main(){
  ios_base::sync_with_stdio(false);
  cout<<fixed<<setprecision(0);
  int i,j,k,n,q;
  cin>>n;
  vector<string> str(n);
  rep(i,n)cin>>str[i];
  vector<pair<string,int>> srt;
  rep(i,n)srt.emplace_back(str[i],i);
  sort(all(srt));
  vector<int> s(n),rnk(n);
  rep(i,n)
    s[i]=srt[i].Y;
  rep(i,n)
    rnk[s[i]]=i;
  set<int> st;
  cin>>q;
  int t,id;
  rep(i,q){
    cin>>t>>id;
    --id;
    if(t==1){
      st.insert(rnk[id]);
    }else if(t==2){
      st.erase(rnk[id]);
    }else{
      auto re=st.lower_bound(rnk[id]);
      if(re==st.end()){
	cout<<-1<<endl;
      }else{
	//cout<<str[id]<<","<<str[s[*re]]<<endl;
	if(str[id].size()<=str[s[*re]].size() && str[id]==str[s[*re]].substr(0,str[id].size()))
	  cout<<s[*re]+1<<endl;
	else
	  cout<<-1<<endl;
      }
    }
  }
  return 0;
}
accuracy: 1
time_ms: 440
memory_kb: 10444
final_rank: 10

code_snippet: #include<stdio.h>
#include<algorithm>
#include<string>
#include<set>
using namespace std;
set<int>Set;
set<int>::iterator it;
int n, Num[101000], LCP[101000];
int st[101000][2], ed[101000];
char p[101000];
struct A{
	int num;
	string S;
	bool operator <(const A &p)const{
		return S < p.S;
	}
}w[101000];
int main(){
	int i, j, s1, s2, top = 0, Q, typ, a, t;
	scanf("%d", &n);
	for (i = 1; i <= n; i++){
		scanf("%s", p);
		w[i].S = p;
		w[i].num = i;
	}
	sort(w + 1, w + n + 1);
	for (i = 1; i <= n; i++)Num[w[i].num] = i;
	for (i = 1; i < n; i++){
		s1 = w[i].S.size(), s2 = w[i + 1].S.size();
		for (j = 0; j < min(s1,s2); j++){
			if (w[i].S[j] != w[i + 1].S[j])break;
		}
		LCP[i] = j;
	}
	for (i = 1; i <= n; i++){
		while (top && st[top][0] > LCP[i - 1]){
			ed[st[top][1]] = i - 1;
			top--;
		}
		top++;
		st[top][0] = w[i].S.size(); st[top][1] = i;
	}
	while (top){
		ed[st[top][1]] = n;
		top--;
	}
	scanf("%d", &Q);
	while (Q--){
		scanf("%d%d", &typ, &a);
		if (typ == 1){
			Set.insert(Num[a]);
		}
		if (typ == 2){
			Set.erase(Set.find(Num[a]));
		}
		if (typ == 3){
			it = Set.lower_bound(Num[a]);
			if (it == Set.end() || *it > ed[Num[a]]){
				printf("-1\n");
			}
			else{
				printf("%d\n", w[*it].num);
			}
		}
	}
	return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 10032
final_rank: 1

code_snippet: #include <limits>
#include <iterator>
#include <utility>
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
namespace lc {
template <typename Traits>
class SegmentTree {
public:
	typedef typename Traits::value_type value_type;
private:
	Traits m_traits;
	std::vector<value_type> m_data;
	int m_size;
	void initialize(){
		for(int i = m_size - 2; i >= 0; --i){
			m_data[i] = m_traits(m_data[i * 2 + 1], m_data[i * 2 + 2]);
		}
	}
	value_type query(int a, int b, int k, int l, int r) const {
		if(r <= a || b <= l){ return m_traits.default_value(); }
		if(a <= l && r <= b){ return m_data[k]; }
		const value_type vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
		const value_type vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
		return m_traits(vl, vr);
	}
public:
	template <typename Iterator>
	SegmentTree(
		Iterator first, Iterator last, const Traits &traits = Traits()) :
		m_size(1), m_traits(traits)
	{
		const int n = std::distance(first, last);
		while(m_size < n){ m_size *= 2; }
		m_data.resize(m_size * 2 - 1, m_traits.default_value());
		std::copy(first, last, m_data.begin() + m_size - 1);
		initialize();
	}
	void update(int i, const value_type &val){
		i += m_size - 1;
		m_data[i] = val;
		while(i > 0){
			i = (i - 1) / 2;
			m_data[i] = m_traits(m_data[i * 2 + 1], m_data[i * 2 + 2]);
		}
	}
	value_type query(int a, int b) const {
		return query(a, b, 0, 0, m_size);
	}
};
}
namespace lc {
template <class T>
struct MinTraits {
	typedef T value_type;
	value_type default_value() const {
		return std::numeric_limits<value_type>::max();
	}
	value_type operator()(const value_type &a, const value_type &b) const {
		return std::min(a, b);
	}
};
}
using namespace std;
typedef pair<string, int> psi;
typedef long long ll;
int main(){
	ios_base::sync_with_stdio(false);
	int n;
	cin >> n;
	vector<psi> table(n);
	for(int i = 0; i < n; ++i){
		cin >> table[i].first;
		table[i].second = i;
	}
	sort(table.begin(), table.end());
	vector<int> inv(n);
	for(int i = 0; i < n; ++i){ inv[table[i].second] = i; }
	vector<int> lcp(n);
	for(int i = 0; i + 1 < n; ++i){
		const int len = min(table[i].first.size(), table[i + 1].first.size());
		for(lcp[i] = 0; lcp[i] < len; ++lcp[i]){
			if(table[i].first[lcp[i]] != table[i + 1].first[lcp[i]]){ break; }
		}
	}
	lc::SegmentTree<lc::MinTraits<int>> lcp_st(lcp.begin(), lcp.end());
	vector<int> range_table(n);
	for(int i = 0; i < n; ++i){
		const int len = table[i].first.size();
		int l = i + 1, r = n;
		while(l < r){
			const int c = l + (r - l) / 2;
			if(lcp_st.query(i, c) >= len){
				l = c + 1;
			}else{
				r = c;
			}
		}
		range_table[i] = l;
	}
	const ll llinf = numeric_limits<ll>::max();
	vector<ll> occur_st_init(n, llinf);
	lc::SegmentTree<lc::MinTraits<ll>> occur_st(
		occur_st_init.begin(), occur_st_init.end());
	int q;
	cin >> q;
	while(q--){
		int t, s;
		cin >> t >> s;
		--s;
		if(t == 1){
			occur_st.update(inv[s], (static_cast<ll>(inv[s]) << 32) | s);
		}else if(t == 2){
			occur_st.update(inv[s], llinf);
		}else if(t == 3){
			const ll k = occur_st.query(inv[s], range_table[inv[s]]);
			if(k >= llinf){
				cout << "-1\n";
			}else{
				cout << (k & 0x7fffffff) + 1 << "\n";
			}
		}
	}
	return 0;
}
accuracy: 1
time_ms: 350
memory_kb: 12348
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define for_(i,a,b) for(int i=a;i<b;++i)
#define for_rev(i,a,b) for(int i=a;i>=b;--i)
#define rep(i,n) for(int i=0;i<(int)(n);++i)
#define allof(a) a.begin(),a.end()
#define minit(a,b) memset(a,b,sizeof(a))
#define size_of(a) (int)a.size()
#define mp make_pair

typedef long long lint;
typedef double Double;
typedef pair< int, int > pii;
typedef unsigned long long ull;
typedef pair<string,int> psi;

const ull B = 1000000007;

int n,q;
string s[100010];
psi ns[100010];
set<int> ss;
vector<ull> v[100010];
int id[100010];

int main() {
	scanf("%d",&n);
	rep(i,n){
		cin>>s[i];
		ns[i]=mp(s[i],i);
		v[i].resize((int)s[i].size()+1);
		ull t=0;
		rep(j,s[i].size()){
			t=t*B+s[i][j];
			v[i][j]=t;
		}
	}
	sort(ns,ns+n);
	rep(i,n) id[ns[i].second]=i;
	scanf("%d",&q);
	while(q--){
		int k,p;
		scanf("%d %d",&k,&p);
		--p;
		if(k==1)ss.insert(id[p]);
		else if(k==2)ss.erase(id[p]);
		else{
			auto it=ss.lower_bound(id[p]);
			int f=0,ret;
			if(it==ss.end())ret=-1;
			else{
				int t=ns[*it].second,l=s[p].size();
				if((int)s[t].size()>=l&&v[t][l-1]==v[p][l-1])f=1;
				if(!f)ret=-1;
				else ret=t+1;
			}
			printf("%d\n",ret);
		}
	}
}
accuracy: 1
time_ms: 170
memory_kb: 28116
final_rank: 7

code_snippet: #include <cstring>
#include <algorithm>
#define REP(i,n) for(int i=0; i<(int)(n); i++)

#define FOR(i,c) for(__typeof((c).begin()) i=(c).begin(); i!=(c).end(); i++)

#include <cstdio>
#include <iostream>
#include <queue>
#include <map>
#include <set>

inline int getInt(){ int s; scanf("%d", &s); return s; }


using namespace std;

struct Node{
  int id;
  map<char, Node *> next;
  Node(){
    id = -1;
  }
};

vector<string> s;
char buff[100000 + 10];

Node *getNext(Node *node, char c){
  if(node->next[c] == NULL)
    node->next[c] = new Node();
  return node->next[c];
}

vector<int> rng;
vector<int> r;

void dfs(Node *node){
  const int id = node->id;
  if(id != -1){
    r.push_back(id);
    FOR(it, node->next)
      dfs(it->second);
    rng[id] = r.size();
  }else{
    FOR(it, node->next)
      dfs(it->second);
  }
}

int main(){
  const int n = getInt();
  rng = vector<int>(n);

  Node *root = new Node();

  REP(i,n){
    scanf("%s", buff);
    const int len = strlen(buff);

    Node *node = root;
    REP(i,len){
      const char c = buff[i];
      node = getNext(node, c);
    }
    node->id = i;
  }

  dfs(root);

  // REP(i,n) printf("%d ", r[i]); puts("");
  // REP(i,n) printf("%d ", rng[i]); puts("");

  vector<int> memo(n);
  REP(i,n) memo[r[i]] = i;

  const int q = getInt();
  set<int> in;
  REP(_,q){
    const int k = getInt();
    const int id = getInt() - 1;

    if(k == 1){
      in.insert(memo[id]);
    }else if(k == 2){
      in.erase(memo[id]);
    }else{
      set<int>::iterator it = in.lower_bound(memo[id]);
      if(it != in.end()){
        const int idx = *it;
        if(idx < rng[id]){
          printf("%d\n", r[idx] + 1);
        }else{
          puts("-1");
        }
      }else{
        puts("-1");
      }
    }

  }


  return 0;
}
accuracy: 1
time_ms: 190
memory_kb: 125048
final_rank: 12