제출 #1338130

#제출 시각아이디문제언어결과실행 시간메모리
1338130huutuanBrperm (RMI20_brperm)C++20
50 / 100
811 ms327680 KiB
#include "brperm.h"

#include <bits/stdc++.h>

using namespace std;

#define int long long

const int N=5e5+10, LG=19;
const pair<int, int> mod={(int)1e9+7, (int)1e9+9}, base={3636, 6767};
pair<int, int> pw[N];

struct Node{
   int sz;
   pair<int, int> val;
   int il, ir;
   Node (int _sz=0, pair<int, int> _val={0, 0}){
      sz=_sz, val=_val;
      il=0;
      ir=0;
   }
   void merge();
};

Node t[N*4];
int tsz=1;

void Node::merge(){
   val={
      (t[il].val.first*pw[t[ir].sz].first+t[ir].val.first)%mod.first,
      (t[il].val.second*pw[t[ir].sz].second+t[ir].val.second)%mod.second,
   };
   sz=t[il].sz+t[ir].sz;
}

struct SegmentTree{
   void build(int k, int l, int r, char a[]){
      if (l==r){
         t[k].sz=1;
         t[k].val={a[l], a[l]};
         return;
      }
      int mid=(l+r)>>1;
      if (!t[k].il) t[k].il=++tsz;
      if (!t[k].ir) t[k].ir=++tsz;
      build(t[k].il, l, mid, a);
      build(t[k].ir, mid+1, r, a);
      t[k].merge();
   }
   void update(int k, int l, int r, int pos, int val){
      if (l==r){
         t[k].sz=1;
         t[k].val={val, val};
         return;
      }
      int mid=(l+r)>>1;
      if (pos<=mid){
         update(t[k].il, l, mid, pos, val);
      }else{
         update(t[k].ir, mid+1, r, pos, val);
      }
      t[k].merge();
   }
   void swap_node(int k, int l, int r){
      if (l==r) return;
      swap(t[k].il, t[k].ir);
      int mid=(l+r)>>1;
      swap_node(t[k].ir, mid+1, r);
      t[k].merge();
   }
} st;

pair<int, int> val[LG][N], val2[LG][N];
char a[N];
int n;

void init(int32_t _n, const char s[]) {
   n=_n;
   for (int i=0; i<n; ++i) val[0][i]={s[i], s[i]};
   pw[0]={1, 1};
   for (int i=1; i<=n; ++i){
      pw[i]={
         pw[i-1].first*base.first%mod.first,
         pw[i-1].second*base.second%mod.second,
      };
   }
   for (int k=1; k<LG; ++k){
      for (int i=0; i+(1<<k)-1<n; ++i){
         val[k][i]={
            (val[k-1][i].first*pw[1<<(k-1)].first+val[k-1][i+(1<<(k-1))].first)%mod.first,
            (val[k-1][i].second*pw[1<<(k-1)].second+val[k-1][i+(1<<(k-1))].second)%mod.second,
         };
      }
   }
   int kk=0;
   while ((1<<(kk+1))<=n) ++kk;
   st.build(1, 0, (1<<kk)-1, a);
   for (int k=0; k<LG; ++k){
      if ((1<<k)>n) break;
      a[0]=s[0];
      for (int i=1, j=0; i<(1<<k); ++i){
         int bit=1<<(k-1);
         for (; j&bit; bit>>=1) j^=bit;
         j^=bit;
         a[j]=s[i];
      }
      st.build(1, 0, (1<<k)-1, a);
      val2[k][0]=t[1].val;
      for (int i=1; i+(1<<k)-1<n; ++i){
         st.swap_node(1, 0, (1<<k)-1);
         st.update(1, 0, (1<<k)-1, (1<<k)-1, s[i+(1<<k)-1]);
         val2[k][i]=t[1].val;
      }
   }
}

int32_t query(int32_t i, int32_t k) {
   if (i+(1<<k)-1>=n) return 0;
   return val[k][i]==val2[k][i];
}

// mt19937 rng(42);

// int rand(int l, int r){
//    return uniform_int_distribution<int>(l, r)(rng);
// }

// char ss[N];

// int32_t main(){
//    int nn=5e5;
//    for (int i=0; i<nn; ++i) ss[i]=rand('a', 'b');
//    init(nn, ss);
//    for (int i=0; i<nn; ++i) query(0, rand(0, 15));
//    return 0;
// }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...