Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma GCC optimize("Ofast")
- #pragma GCC target("popcnt")
- #pragma GCC target("avx,avx2,fma")
- #include <bits/stdc++.h>
- #define watch(x) std::cerr << #x << " = " << (x)
- #define watchln(x) watch(x) << std::endl
- using ull = unsigned long long;
- ull table[65][65];
- const int TABLE_FILLED = [](){
- for (int begin = 0; begin <= 64; begin++) {
- for (int end = begin; end <= 64; end++) {
- const auto fi = (begin == 64) ? ull(0) : (ull(-1) << begin);
- const auto se = (end == 0) ? ull(0) : (ull(-1) >> (64 - end));
- table[begin][end] = fi & se;
- }
- }
- return 1;
- }();
- int cntbit(ull mask, int begin, int end) {
- return __builtin_popcountll(mask & table[begin][end]);
- }
- template<int value>
- void setbit(ull& mask, int begin, int end) {
- mask = (mask & ~table[begin][end]) | (value == 1 ? table[begin][end] : ull(0));
- }
- void setbit(ull& mask, int begin, int end, int v) {
- if (v) { setbit<1>(mask,begin,end); }
- else { setbit<0>(mask,begin,end); }
- }
- #define all(x) (x).begin(),(x).end()
- template<int size>
- struct Bitset {
- std::array<ull, (size + 63)/ 64> data;
- void clear() { std::fill(all(data), ull(0)); }
- Bitset() { clear(); }
- void set(int p, int v) {
- if (v) { setbit<1>(data[p / 64], p % 64, p % 64+1); }
- else { setbit<0>(data[p / 64], p % 64, p % 64+1); }
- }
- int get(int p) {
- return (data[p / 64] >> (p % 64)) & 1;
- }
- int& set(int l, int r, int v, int& delta) {
- const int gl = l / 64, gr = r / 64;
- if (gl == gr) {
- delta -= __builtin_popcountll(data[gl]);
- setbit(data[gl], l % 64, r % 64 + 1, v);
- delta += __builtin_popcountll(data[gl]);
- } else {
- delta -= __builtin_popcountll(data[gl]) + __builtin_popcountll(data[gr]);
- setbit(data[gl], l%64,64,v);
- setbit(data[gr], 0,r%64+1,v);
- delta += __builtin_popcountll(data[gl]) + __builtin_popcountll(data[gr]);
- const ull val = (v) ? ull(-1) : ull(0);
- const int add = v * 64;
- for (int g = gl+1; g < gr; g++) {
- delta += add - __builtin_popcountll(data[g]);
- data[g] = val;
- }
- }
- return delta;
- }
- void set(int l, int r, int v) {
- int delta = 0;
- set(l,r,v,delta);
- }
- int get(int l, int r) {
- const int gl = l / 64, gr = r / 64;
- if (gl == gr) {
- return cntbit(data[gl], l % 64, r % 64 + 1);
- } else {
- int answ = cntbit(data[gl], l%64,64) + cntbit(data[gr], 0,r%64+1);
- for (int g = gl+1; g < gr; g++) {
- answ += __builtin_popcountll(data[g]);
- }
- return answ;
- }
- }
- };
- template<int size, int gsize>
- struct SD {
- Bitset<size> data;
- std::vector<int> gcnt, gset;
- SD() : data(), gcnt(size / gsize, 0), gset(size / gsize, -1) { }
- void clear() {
- data.clear();
- std::fill(all(gcnt), 0);
- std::fill(all(gset),-1);
- }
- void push(int g) {
- if (gset[g] == -1) return;
- int v = gset[g];
- gset[g] = -1;
- const int begin = g * gsize;
- const int after = (begin + gsize);
- data.set(begin, after-1, v);
- gcnt[g] = gsize * v;
- }
- void set(int p, int v) {
- push(p / gsize);
- gcnt[p / gsize] += v - data.get(p);
- data.set(p, v);
- }
- template<typename T>
- void build(const std::vector<T>& arr) {
- for (int i = 0; i < (int)arr.size(); i++) {
- set(i, arr[i]);
- }
- }
- void set(int l, int r, int v) {
- const int gl = l / gsize, gr = r / gsize;
- push(gl); push(gr);
- if (gl == gr) {
- int delta = 0;
- gcnt[gl] += data.set(l, r, v, delta);
- } else {
- int dl = 0, dr = 0;
- const int after = (gl + 1) * gsize, begin = gr * gsize;
- gcnt[gl] += data.set(l, after-1, v, dl);
- gcnt[gr] += data.set(begin, r, v, dr);
- for (int g = gl+1; g < gr; g++) {
- gset[g] = v;
- gcnt[g] = v * gsize;
- }
- }
- }
- int get(int l, int r) {
- const int gl = l / gsize, gr = r / gsize;
- push(gl); push(gr);
- int answ = 0;
- if (gl == gr) {
- answ += data.get(l,r);
- } else {
- const int after = (gl + 1) * gsize, begin = gr * gsize;
- answ += data.get(l, after-1) + data.get(begin, r);
- for (int g = gl+1; g < gr; g++) { answ += gcnt[g]; }
- }
- return answ;
- }
- };
- const int mod = (int)1e9+7;
- int pow(int a, int n) {
- int r = 1;
- while (n > 0) {
- if (n % 2) {
- r = int(1LL * a * r % mod);
- }
- a = int(1LL * a * a % mod);
- n /= 2;
- }
- return r;
- }
- const int NMAX = 1024 * 1024;
- int fact[NMAX+1], ifact[NMAX+1];
- std::vector<SD<128 * 1024, 1024>> sd(26);
- int main() {
- fact[0] = 1;
- for (int i = 1; i <= NMAX; i++) {
- fact[i] = int(1LL * fact[i-1] * i % mod);
- }
- ifact[NMAX] = pow(fact[NMAX], mod-2);
- for (int i = NMAX-1; i >= 0; --i) {
- ifact[i] = int(1LL * ifact[i+1] * (i+1) % mod);
- }
- std::ios_base::sync_with_stdio(false);
- std::cin.tie(0);
- int n; std::cin >> n;
- std::string s; std::cin >> s;
- std::vector<int> arr(n);
- for (char c = 'a'; c <= 'z'; c++) {
- for (int i = 0; i < n; i++) {
- arr[i] = (s[i] == c);
- }
- sd[c-'a'].build(arr);
- }
- int q; std::cin >> q;
- for (int id = 0; id < q; id++) {
- std::cin >> s;
- int l, r; std::cin >> l >> r;
- l--,r--;
- if (s == "get") {
- int answ = fact[r-l+1];
- for (int i = 0; i < 26; i++) {
- assert(l <= r);
- auto tmp = sd[i].get(l,r);
- assert(tmp >= 0);
- answ = int(1LL * answ * ifact[tmp] % mod);
- }
- std::cout << answ << std::endl;
- } else {
- char curr; std::cin >> curr;
- int j = curr - 'a';
- for (int i = 0; i < j; i++) {
- sd[i].set(l,r,0);
- }
- sd[j].set(l,r,1);
- for (int i = j+1; i < 26; i++) {
- sd[i].set(l,r,0);
- }
- }
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement