Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //satyaki3794
- #include <bits/stdc++.h>
- #define ff first
- #define ss second
- #define pb push_back
- #define MOD (1000000007LL)
- #define LEFT(n) (2*(n))
- #define RIGHT(n) (2*(n)+1)
- using namespace std;
- typedef long long ll;
- typedef pair<int, int> ii;
- typedef pair<int, ii> iii;
- ll pwr(ll base, ll p, ll mod = MOD){
- ll ans = 1;while(p){if(p&1)ans=(ans*base)%mod;base=(base*base)%mod;p/=2;}return ans;
- }
- ll gcd(ll a, ll b){
- if(b == 0) return a;
- return gcd(b, a%b);
- }
- const int N = 1000*1000+2;
- int n, sz, ticks, trie[N][26], BIT[N], subtree_l[N], subtree_r[N];
- int q, lo[100005], hi[100005], ans[100005];
- ll threshold[100005];
- vector<int> T, query_sets[100005], check[100005];
- void update(int idx, int val){
- while(idx <= ticks){
- BIT[idx] += val;
- idx += idx & (-idx);
- }
- }
- int query(int idx){
- int ans = 0;
- while(idx){
- ans += BIT[idx];
- idx -= idx & (-idx);
- }
- return ans;
- }
- void insert(string str, vector<int> &v){
- int curr = 0;
- for(int i=0;i<(int)str.length();i++){
- int dir = str[i] - 'a';
- if(trie[curr][dir] == -1)
- trie[curr][dir] = ++sz;
- curr = trie[curr][dir];
- }
- v.pb(curr);
- }
- void dfs(int v){
- subtree_l[v] = ++ticks;
- for(int dir=0;dir<26;dir++)
- if(trie[v][dir] != -1)
- dfs(trie[v][dir]);
- subtree_r[v] = ticks;
- }
- ll get_value_till(int z){
- memset(BIT, 0, sizeof(BIT));
- for(int i=1;i<=z;i++){
- int trie_node = T[i-1];
- update(subtree_l[trie_node], 1);
- update(subtree_r[trie_node]+1, -1);
- }
- ll ans = 0;
- for(auto node : query_sets[1])
- ans += query(subtree_l[node]);
- return ans;
- }
- int main(){
- ios_base::sync_with_stdio(0);
- cin.tie(0);
- // freopen("test6.in", "r", stdin);
- // freopen("test6.out", "w", stdout);
- memset(trie, -1, sizeof(trie));
- sz = 0;
- cin>>n;
- for(int i=1;i<=n;i++){
- string str;
- cin>>str;
- insert(str, T);
- }
- cin>>q;
- for(int i=1;i<=q;i++){
- int z;
- cin>>z>>threshold[i];
- while(z--){
- string str;
- cin>>str;
- insert(str, query_sets[i]);
- }
- ans[i] = MOD;
- lo[i] = 1; hi[i] = n;
- }
- dfs(0);
- // for(auto it : T) cout<<it<<" ";cout<<endl;
- // for(auto it : query_sets[1]) cout<<it<<" ";cout<<endl;
- // cout<<"subtree_l: ";for(int i=0;i<=sz;i++) cout<<subtree_l[i]<<" ";cout<<endl;
- // cout<<"subtree_r: ";for(int i=0;i<=sz;i++) cout<<subtree_r[i]<<" ";cout<<endl;
- // cout<<threshold[1]<<endl;
- // cout<<get_value_till(225)<<endl;
- // cout<<get_value_till(226)<<endl;
- // cout<<get_value_till(14550)<<endl;
- // cout<<get_value_till(14551)<<endl;
- bool more_iterations = true;
- while(more_iterations){
- more_iterations = false;
- memset(BIT, 0, (ticks+1)*sizeof(BIT[0]));
- for(int i=1;i<=n;i++)
- check[i].clear();
- for(int i=1;i<=q;i++)
- if(lo[i] <= hi[i]){
- check[(lo[i]+hi[i])/2].pb(i);
- more_iterations = true;
- }
- for(int i=1;i<=n;i++){
- int trie_node = T[i-1];
- update(subtree_l[trie_node], 1);
- update(subtree_r[trie_node]+1, -1);
- for(auto S : check[i]){
- ll val = 0;
- for(auto node : query_sets[S]){
- val += query(subtree_l[node]);
- }
- if(val >= threshold[S]){
- ans[S] = min(ans[S], i);
- hi[S] = i-1;
- }
- else{
- lo[S] = i+1;
- }
- }
- }
- }
- for(int i=1;i<=q;i++){
- if(ans[i] == MOD) ans[i] = -1;
- cout<<ans[i]<<endl;
- }
- return 0;
- }
Add Comment
Please, Sign In to add comment