Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- using namespace std;
- #define all(x) (x).begin(), (x).end()
- typedef long long ll;
- inline int nxt() {
- int x;
- cin >> x;
- return x;
- }
- void Build(const string& init, vector<int>& suffArray, vector<int>& lcp) {
- string s = init;
- s.push_back(char(0));
- int n = s.size();
- vector<int> head(max(n, 256));
- vector<int> color(n);
- vector<int> colorSub(n);
- vector<int> suffArraySub(n);
- lcp.resize(n);
- suffArray.resize(n);
- for (int i = 0; i < s.size(); ++i) {
- ++head[s[i]];
- }
- for (int i = 1; i < 256; ++i) {
- head[i] += head[i - 1];
- }
- for (int i = 255; i > 0; --i) {
- head[i] = head[i - 1];
- }
- head[0] = 0;
- for (int i = 0; i < s.size(); ++i) {
- suffArray[head[s[i]]] = i;
- ++head[s[i]];
- }
- int numClasses = 1;
- head[0] = 0;
- for (int i = 1; i < s.size(); ++i) {
- if (s[suffArray[i - 1]] != s[suffArray[i]]) {
- ++numClasses;
- head[numClasses - 1] = i;
- }
- color[suffArray[i]] = numClasses - 1;
- }
- for (int k = 1; k < s.size(); k *= 2) {
- for (int i = 0; i < s.size(); ++i) {
- int first = suffArray[i] - k;
- if (first < 0) {
- first += s.size();
- }
- suffArraySub[head[color[first]]] = first;
- ++head[color[first]];
- }
- suffArray = suffArraySub;
- int second;
- pair<int, int> prevClasses, curClasses;
- curClasses = { -1, 0 };
- numClasses = 0;
- for (int i = 0; i < s.size(); ++i) {
- prevClasses = curClasses;
- second = suffArray[i] + k;
- if (second >= s.size()) {
- second -= s.size();
- }
- curClasses = { color[suffArray[i]], color[second] };
- if (curClasses != prevClasses) {
- ++numClasses;
- head[numClasses - 1] = i;
- }
- colorSub[suffArray[i]] = numClasses - 1;
- }
- color = colorSub;
- if (numClasses == s.size())
- break;
- }
- vector <int> pos;
- int curLcp = 0;
- pos.resize(s.size());
- for (int i = 0; i < s.size(); ++i) {
- pos[suffArray[i]] = i;
- }
- lcp.resize(s.size());
- for (int i = 0; i < s.size(); ++i) {
- if (pos[i] == s.size() - 1) {
- lcp[pos[i]] = 0;
- curLcp = 0;
- continue;
- }
- while (s[(i + curLcp) % s.size()] == s[(suffArray[pos[i] + 1] + curLcp) % s.size()]) {
- ++curLcp;
- }
- lcp[pos[i]] = curLcp;
- --curLcp;
- if (curLcp < 0)
- curLcp = 0;
- }
- }
- void BuildSparseTable(const vector <int>& a, vector < vector <int> >& sparseTable) {
- int logSize = 0;
- while ((1 << logSize) < a.size()) {
- ++logSize;
- }
- logSize = 19; // <-- THINK HERE!
- sparseTable.assign(a.size(), vector <int> (logSize + 1));
- for (int i = 0; i < a.size(); ++i) {
- sparseTable[i][0] = a[i];
- }
- for (int k = 1; k <= logSize; ++k) {
- for (int i = 0; i + (1 << k) <= a.size(); ++i) {
- sparseTable[i][k] = min(sparseTable[i][k - 1], sparseTable[i + (1 << (k - 1))][k - 1]);
- }
- }
- }
- int GetMin(int l, int r, const vector < vector <int> >& sparseTable) {
- assert(l < r);
- int sz = 31 - __builtin_clz(r - l);
- return min(sparseTable[l][sz], sparseTable[r - (1 << sz)][sz]);
- }
- pair<int, int> GetGoodInterval(const vector<vector<int>>& sparse, int pos, int x) {
- int l = pos, r = (int)sparse.size();
- while (r > l + 1) {
- int m = (l + r) / 2;
- if (GetMin(pos, m + 1, sparse) >= x) {
- l = m;
- } else {
- r = m;
- }
- }
- int ans_r = r;
- l = 0, r = pos + 1;
- while (r > l + 1) {
- int m = (l + r) / 2;
- if (GetMin(m, pos + 1, sparse) >= x) {
- l = m;
- } else {
- r = m;
- }
- }
- int ans_l = l;
- return {ans_l, ans_r};
- }
- struct Fenwick {
- vector<ll> t;
- Fenwick() {}
- Fenwick(int n) : t(n) {
- }
- void add(int pos, ll delta) {
- assert(0 <= pos && pos < (int) t.size());
- for (int i = pos; i < (int) t.size(); i |= i + 1) {
- t[i] += delta;
- }
- }
- ll get(int r) {
- ll res = 0;
- for (int i = r - 1; i >= 0; i = (i & (i + 1)) - 1) {
- res += t[i];
- }
- return res;
- }
- ll get(int l, int r) {
- return get(r) - get(l);
- }
- };
- struct Kostya {
- static constexpr int base = 1 << 18;
- vector<int> t[base * 2];
- Fenwick fw[base * 2];
- vector<int> p;
- vector<int> a;
- int lb(int v, int x, bool check) {
- auto it = lower_bound(t[v].begin(), t[v].end(), x);
- if (check) {
- assert(it != t[v].end() && *it == x);
- }
- return it - t[v].begin();
- }
- Kostya() {}
- void init(int n, const vector<int>& p0) {
- p = p0;
- a.resize(n);
- for (int i = 0; i < n; ++i) {
- t[i + base] = {p[i]};
- fw[i + base] = Fenwick(1);
- }
- for (int i = base - 1; i > 0; --i) {
- set_union(t[i * 2].begin(), t[i * 2].end(), t[i * 2 + 1].begin(), t[i * 2 + 1].end(), back_inserter(t[i]));
- fw[i] = Fenwick((int) t[i].size());
- }
- }
- void change(int pos, int x) {
- int valy = p[pos];
- int delta = x - a[pos];
- a[pos] += delta;
- for (int v = base + pos; v > 0; v /= 2) {
- int w = lb(v, valy, true);
- fw[v].add(w, delta);
- }
- }
- int down_, up_;
- int get(int l, int r, int v = 1, int cl = 0, int cr = base) {
- if (l <= cl && cr <= r) {
- int wr = lb(v, up_, false);
- int wl = lb(v, down_, false);
- return fw[v].get(wl, wr);
- }
- if (r <= cl || cr <= l) {
- return 0;
- }
- int cc = (cl + cr) / 2;
- return get(l, r, v * 2, cl, cc) + get(l, r, v * 2 + 1, cc, cr);
- }
- int getSum(int l, int r, int down, int up) { // sum{a[x] in [l, r) | down <= x < up}
- down_ = down, up_ = up;
- return get(l, r);
- }
- };
- Kostya zlp;
- int main() {
- string s, t;
- cin >> s >> t;
- reverse(all(s));
- reverse(all(t));
- int n = s.length();
- int m = t.length();
- vector<int> a(n);
- for (int i = 0; i < n; ++i) {
- a[i] = nxt();
- }
- reverse(all(a));
- vector<int> sa, lcp;
- string st = s + "#" + t;
- Build(st, sa, lcp);
- sa.erase(sa.begin());
- lcp.erase(lcp.begin());
- vector<int> pos(sa.size());
- for (int i = 0; i < (int)sa.size(); ++i) {
- pos[sa[i]] = i;
- }
- vector<vector<int>> sparse;
- BuildSparseTable(lcp, sparse);
- zlp.init(st.size(), sa);
- for (int i = 0; i < n; ++i) {
- zlp.change(pos[i], a[i]);
- }
- int q = nxt();
- while (q--) {
- int t = nxt();
- if (t == 1) {
- int x = nxt(), y = nxt();
- zlp.change(pos[n - 1 - x], y);
- } else {
- int t1 = nxt(), t2 = nxt() + 1, s1 = nxt(), s2 = nxt() + 1;
- t1 = m - t1;
- t2 = m - t2;
- swap(t1, t2);
- s1 = n - s1;
- s2 = n - s2;
- swap(s1, s2);
- if (s2 - s1 < t2 - t1) {
- cout << 0 << endl;
- continue;
- }
- int idx = pos[t1 + n + 1];
- auto seg = GetGoodInterval(sparse, idx, t2 - t1);
- cout << zlp.getSum(seg.first, seg.second, s1, s2 - t2 + t1) << endl;
- }
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment