• [THUSC2016]补退选


    Description

    维护一个字符串集合,有三种事件,加入一个字符串,删除一个字符串,询问最早在哪个事件之后,以某个串为前缀的字符串数量超过(k),强制在线。(n le 100000,|S| le 60),输入中的所有字符串只会包含前(10)个小写字母。

    Solution

    建立(Trie)树维护字符串集合,在(Trie)树上的每一个节点开一个(vector),用来记录子树内的结束节点到达某个值的最早时刻,查询时直接找到前缀对应节点即可。

    Code

    #include <bits/stdc++.h>
    using namespace std;
    
    const int _ = 1e6 + 10;
    int N, tim;
    
    inline int ty() {
      char ch = getchar();
      int x = 0, f = 1;
      while (ch < '0' || ch > '9') {
        if (ch == '-') f = -1;
        ch = getchar();
      }
      while (ch >= '0' && ch <= '9') {
        x = x * 10 + ch - '0';
        ch = getchar();
      }
      return x * f;
    }
    
    inline int getstr(char *s) {
      char ch = getchar();
      int cnt = 0;
      while (ch >= 'a' && ch <= 'j') {
        s[++cnt] = ch;
        ch = getchar();
      }
      return cnt;
    }
    
    struct Trie {
      int trie[_][10], cnt[_], tot;
      vector<int> num[_];
      void insert(char *s, int len) {
        int x = 0;
        for (int i = 1; i <= len; ++i) {
          int ch = s[i] - 'a';
          if (!trie[x][ch]) trie[x][ch] = ++tot;
          x = trie[x][ch];
          ++cnt[x];
          if (num[x].size() < cnt[x]) num[x].push_back(tim);
        }
      }
      void erase(char *s, int len) {
        int x = 0;
        for (int i = 1; i <= len; ++i) {
          int ch = s[i] - 'a';
          x = trie[x][ch];
          --cnt[x];
        }
      }
      int query(char *s, int k, int len) {
        int x = 0;
        for (int i = 1; i <= len; ++i) {
          int ch = s[i] - 'a';
          if (!trie[x][ch]) return -1;
          x = trie[x][ch];
        }
        if (num[x].size() <= k)
          return -1;
        else
          return num[x][k];
      }
    } tr;
    
    int main() {
    #ifndef ONLINE_JUDGE
      freopen("select.in", "r", stdin);
      freopen("select.out", "w", stdout);
    #endif
      N = ty();
      int last = 0;
      for (tim = 1; tim <= N; ++tim) {
        int op = ty();
        char s[65];
        int len = getstr(s);
        if (op == 1)
          tr.insert(s, len);
        else if (op == 2)
          tr.erase(s, len);
        else if (op == 3) {
          int a = ty(), b = ty(), c = ty();
          int k = (1ll * a * abs(last) + b) % c;
          printf("%d
    ", last = tr.query(s, k, len));
        }
      }
      return 0;
    }
    
  • 相关阅读:
    Android开发之EditText属性详解
    android开发如何在页面之间传参
    jquery中attr和prop的区别
    Laravel 5.2--改变数据库字段值,编辑时候,默认选中
    Laravel 5.2--git冲突error: Your local changes to the following files would be overwritten by merge:
    Laravel 5.2--如何让表单提交错误,不清空?
    Apache 和 Tomcat联系和区别
    mac 上如何安装非app store上的下载的软件-------打开未知来源
    &#65279导致页面顶部空白一行解决方法
    面向对象设计的三个基本特征
  • 原文地址:https://www.cnblogs.com/newbielyx/p/12146402.html
Copyright © 2020-2023  润新知