智乃的Notepad(Hard version) (trie树 + 离线) 2025牛客寒假算法底子集训营 ...

打印 上一主题 下一主题

主题 1012|帖子 1012|积分 3036

学习到的内容 :  初步了解并使用trie树, 初步了解了离线算法
对于扣问的区间的字符串建一个trie树的话, 每个节点(除去根节点, 或者是边数)走两次, 最长的字符串不消回退, 答案就是 节点数 * 2 - 最长串的长度
求每次扣问区间形成的trie树, 可以用离线算法, 给扣问r端点排序, 这时只必要减去左边不包含的区间的节点就行了. 对于重复的边, 每次都让他盘算为新来的字符串的长度, 不盘算为以前的字符串的长度
  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. using i64 = long long;
  4. template <typename T>
  5. struct Fenwick {
  6.     int n;
  7.     std::vector<T> a;
  8.    
  9.     Fenwick(int n_ = 0) {
  10.         init(n_);
  11.     }
  12.    
  13.     void init(int n_) {
  14.         n = n_;
  15.         a.assign(n, T{});
  16.     }
  17.    
  18.     void add(int x, const T &v) {
  19.         for (int i = x; i <= n; i += i & -i) {
  20.             a[i] = a[i] + v;
  21.         }
  22.     }
  23.    
  24.     T sum(int x) {
  25.         T ans{};
  26.         for (int i = x; i > 0; i -= i & -i) {
  27.             ans = ans + a[i];
  28.         }
  29.         return ans;
  30.     }
  31.    
  32.     T rangeSum(int l, int r) {
  33.         return sum(r) - sum(l - 1);
  34.     }
  35.    
  36. };
  37. Fenwick<int> fenwick(1000001);
  38. int nex[1000001][26], tot;
  39. int cnt[1000001];  // 该结点结尾的字符串的数量
  40. int belongto[1000001];
  41. struct Trie {
  42.   
  43.   void insert(string s, int idx, int t = 1) {  // 插入字符串
  44.     int p = 0;
  45.     for (int i = 0; i < s.length(); i++) {
  46.       int c = s[i] - 'a';
  47.       if (!nex[p][c]) nex[p][c] = ++tot;  // 如果没有,就添加结点
  48.       p = nex[p][c];
  49. ;
  50.       if(belongto[p]) fenwick.add(belongto[p], -1);
  51.       belongto[p] = idx;
  52.       fenwick.add(belongto[p], 1);
  53.     }
  54.     cnt[p] += t;
  55.   }
  56.   bool find(string s) {  // 查找字符串
  57.     int p = 0;
  58.     for (int i = 0; i < s.length(); i++) {
  59.       int c = s[i] - 'a';
  60.       if (!nex[p][c]) return 0;
  61.       p = nex[p][c];
  62.     }
  63.     return cnt[p];
  64.   }
  65. };
  66. template<class Info>
  67. struct SegmentTree {
  68.     int n;
  69.     std::vector<Info> info;
  70.     SegmentTree() : n(0) {}
  71.     SegmentTree(int n_, Info v_ = Info()) {
  72.         init(n_, v_);
  73.     }
  74.     template<class T>
  75.     SegmentTree(std::vector<T> init_) {
  76.         init(init_);
  77.     }
  78.     void init(int n_, Info v_ = Info()) {
  79.         init(std::vector(n_, v_));
  80.     }
  81.     template<class T>
  82.     void init(std::vector<T> init_) {
  83.         n = init_.size();
  84.         info.assign(4 << std::__lg(n), Info());
  85.         std::function<void(int, int, int)> build = [&](int p, int l, int r) {
  86.             if (r - l == 1) {
  87.                 info[p] = init_[l];
  88.                 return;
  89.             }
  90.             int m = (l + r) / 2;
  91.             build(2 * p, l, m);
  92.             build(2 * p + 1, m, r);
  93.             pull(p);
  94.         };
  95.         build(1, 0, n);
  96.     }
  97.     void pull(int p) {
  98.         info[p] = info[2 * p] + info[2 * p + 1];
  99.     }
  100.     void modify(int p, int l, int r, int x, const Info &v) {
  101.         if (r - l == 1) {
  102.             info[p] = v;
  103.             return;
  104.         }
  105.         int m = (l + r) / 2;
  106.         if (x < m) {
  107.             modify(2 * p, l, m, x, v);
  108.         } else {
  109.             modify(2 * p + 1, m, r, x, v);
  110.         }
  111.         pull(p);
  112.     }
  113.     void modify(int p, const Info &v) {
  114.         modify(1, 1, n, p, v);
  115.     }
  116.     Info rangeQuery(int p, int l, int r, int x, int y) {
  117.         if (l >= y || r <= x) {
  118.             return Info();
  119.         }
  120.         if (l >= x && r <= y) {
  121.             return info[p];
  122.         }
  123.         int m = (l + r) / 2;
  124.         return rangeQuery(2 * p, l, m, x, y) + rangeQuery(2 * p + 1, m, r, x, y);
  125.     }
  126.     Info rangeQuery(int l, int r) {
  127.         return rangeQuery(1, 1, n, l, r + 1);
  128.     }
  129.     template<class F>
  130.     int findFirst(int p, int l, int r, int x, int y, F &&pred) {
  131.         if (l >= y || r <= x) {
  132.             return -1;
  133.         }
  134.         if (l >= x && r <= y && !pred(info[p])) {
  135.             return -1;
  136.         }
  137.         if (r - l == 1) {
  138.             return l;
  139.         }
  140.         int m = (l + r) / 2;
  141.         int res = findFirst(2 * p, l, m, x, y, pred);
  142.         if (res == -1) {
  143.             res = findFirst(2 * p + 1, m, r, x, y, pred);
  144.         }
  145.         return res;
  146.     }
  147.     template<class F>
  148.     int findFirst(int l, int r, F &&pred) {
  149.         return findFirst(1, 1, n, l, r + 1, pred);
  150.     }
  151.     template<class F>
  152.     int findLast(int p, int l, int r, int x, int y, F &&pred) {
  153.         if (l >= y || r <= x) {
  154.             return -1;
  155.         }
  156.         if (l >= x && r <= y && !pred(info[p])) {
  157.             return -1;
  158.         }
  159.         if (r - l == 1) {
  160.             return l;
  161.         }
  162.         int m = (l + r) / 2;
  163.         int res = findLast(2 * p + 1, m, r, x, y, pred);
  164.         if (res == -1) {
  165.             res = findLast(2 * p, l, m, x, y, pred);
  166.         }
  167.         return res;
  168.     }
  169.     template<class F>
  170.     int findLast(int l, int r, F &&pred) {
  171.         return findLast(1, 1, n, l, r + 1, pred);
  172.     }
  173. };
  174. constexpr int inf = 1E9 + 1;
  175. struct Info {
  176.     int max = -inf;
  177.     int min = inf;
  178. };
  179. Info operator+(const Info &a, const Info &b) {
  180.     return { std::max(a.max, b.max), std::min(a.min, b.min) };
  181. }
  182. struct qur {
  183.         int l, idx;
  184. };
  185. void solve(){
  186.        
  187.         int n, m;
  188.         cin >> n >> m;
  189.         vector<string> s(n + 1);
  190.         SegmentTree<Info> maxlen(n + 1);
  191.         for(int i = 1; i <= n; i++) cin >> s[i], maxlen.modify(i, {(int)s[i].length(),(int)s[i].length()});
  192.         vector<vector<qur>> xun(n + 1);
  193.         for(int i = 1; i <= m; i++) {
  194.                 int l, r;
  195.                 cin >> l >> r;
  196.                 xun[r].push_back({l, i});
  197.         }
  198.         Trie trie;
  199.         vector<int> ans(m + 1);
  200.         for(int i = 1; i <= n; i++) {
  201.                 trie.insert(s[i], i);
  202.                 for(auto it : xun[i]) {
  203.                         int l = it.l, idx = it.idx;
  204.                         auto mxln = maxlen.rangeQuery(l, i).max;
  205.                         ans[idx] = fenwick.rangeSum(l, i) * 2 - mxln;
  206.                 }
  207.         }
  208.         for(int i = 1; i <= m; i++)  cout << ans[i] << endl;
  209.        
  210. }
  211. int main(){
  212.         std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
  213.         int T = 1;
  214.         //cin >> T;
  215.     // cout << 1 << endl;
  216.         while(T--) solve();
  217.         return 0;
  218. }
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

莫张周刘王

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表