前缀总和为o(n)级别的, 然后把前缀hash一下变成求区间本质不同数字的个数。
或者不用hash丢到字典树上去就好了。
#pragma GCC optimize(2) #pragma GCC optimize(3) #include<bits/stdc++.h> #define LL long long #define LD long double #define ull unsigned long long #define fi first #define se second #define mk make_pair #define PLL pair<LL, LL> #define PLI pair<LL, int> #define PII pair<int, int> #define SZ(x) ((int)x.size()) #define ALL(x) (x).begin(), (x).end() #define fio ios::sync_with_stdio(false); cin.tie(0); using namespace std; const int N = 1e5 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 998244353; const double eps = 1e-8; const double PI = acos(-1); template<class T, class S> inline void add(T& a, S b) {a += b; if(a >= mod) a -= mod;} template<class T, class S> inline void sub(T& a, S b) {a -= b; if(a < 0) a += mod;} template<class T, class S> inline bool chkmax(T& a, S b) {return a < b ? a = b, true : false;} template<class T, class S> inline bool chkmin(T& a, S b) {return a > b ? a = b, true : false;} const int B = (int)1e9 + 9; int n; string s[N]; vector<ull> hs[N]; map<ull, int> Map; char t[N]; int Rt[N], treecnt; struct Node { int sum, ls, rs; } a[N * 40]; void update(int p, int val, int l, int r, int &x, int y) { x = ++treecnt; a[x] = a[y]; a[x].sum += val; if(l == r) return; int mid = l + r >> 1; if(p <= mid) update(p, val, l, mid, a[x].ls, a[y].ls); else update(p, val, mid + 1, r, a[x].rs, a[y].rs); } int query(int L, int R, int l, int r, int x) { if(!x || R < l || r < L) return 0; if(L <= l && r <= R) return a[x].sum; int mid = l + r >> 1; return query(L, R, l, mid, a[x].ls) + query(L, R, mid + 1, r, a[x].rs); } void init() { Map.clear(); treecnt = 0; } int main() { while(scanf("%d", &n) != EOF) { init(); for(int i = 1; i <= n; i++) { scanf("%s", t); s[i] = t; } for(int i = 1; i <= n; i++) { hs[i].resize(SZ(s[i])); hs[i][0] = s[i][0]; for(int j = 1; j < SZ(s[i]); j++) { hs[i][j] = hs[i][j - 1] * B + s[i][j]; } } for(int i = 1, j; i <= n; i++) { Rt[i] = Rt[i - 1]; for(auto &t : hs[i]) { j = Map[t]; update(i, 1, 1, n, Rt[i], Rt[i]); if(j) update(j, -1, 1, n, Rt[i], Rt[i]); Map[t] = i; } } int q, Z = 0; scanf("%d", &q); while(q--) { int L, R; scanf("%d%d", &L, &R); L = (Z + L) % n + 1; R = (Z + R) % n + 1; if(L > R) swap(L, R); Z = query(L, R, 1, n, Rt[R]); printf("%d ", Z); } } return 0; } /* */