• 2019南京ICPC(重现赛) F


    题目链接:https://nanti.jisuanke.com/t/42400

    这还是去年去现场赛打的,当时菜的不行,就白给了。最近学了主席树套树状数组,感觉好强的数据结构啊。我们学长说这题挺简单,建字典树dfs序,跑cdq分治就好了(%%%)。本菜鸡发现这题主席树套树状数组也能做。

    题意:给你n个字符串,m个操作。操作1交换俩个字符串,操作2,给定一个字符串s,数字k, l, r, 求l ~ r与s公共前缀大于等于k的字符串的个数。

    首先考虑没有修改,那么就只有操作2,设f[i]为第i个字符串结尾的dfn序。把要询问的字符串在字典树里面第k的位置x求出来。那么就变成求in[x]~out[x]中存在的f[l] ~ f[r]数量,考虑是区间询问,所以用主席树。我们在每个in[x]上建值域线段树(1, n)并在i上加1。就可以变成求in[x]~out[x]中存在l~r的数量,很明显的主席树。然后考虑修改,每次修改会把f[i]和f[j]的位置交换,所以就交换了值域i, j。

      1 #include <bits/stdc++.h>
      2 
      3 using namespace std;
      4 
      5 const int N = 2e5 + 10;
      6 
      7 int n, m;
      8 
      9 char s[N];
     10 
     11 int f[N];
     12 
     13 struct Trie{
     14     int son[N][26], idx = 0;
     15     int in[N], out[N], num = 0;
     16     int insert(char *s)
     17     {
     18         int p = 0;
     19         for (int i = 0; s[i]; i ++)
     20         {
     21             int u = s[i] - 'a';
     22             if(!son[p][u])
     23             son[p][u] = ++ idx;
     24             p = son[p][u];
     25         }
     26         return p;
     27     } 
     28     void dfs(int x)
     29     {
     30         in[x] = ++ num;
     31         for (int i = 0; i < 26; i ++)
     32             if(son[x][i])
     33                 dfs(son[x][i]);
     34         out[x] = num;
     35     }
     36     int find(char* s, int k)
     37     {
     38         int p = 0;
     39         for (int i = 0; i < k; i ++)
     40         {
     41             int u = s[i] - 'a';
     42             if(!son[p][u])
     43             return -1;
     44             p = son[p][u];
     45         }
     46         return p;
     47     }
     48 }t;
     49 
     50 struct Seg{
     51     int l, r;
     52     int val;
     53 }tr[N * 100];
     54 
     55 int root[N];
     56 int num;
     57 
     58 void build(int &rt, int l, int r)
     59 {
     60     if(!rt)
     61     rt = ++ num;
     62     if(l == r) return ;
     63     int mid = l + r >> 1;
     64     build(tr[rt].l, l, mid);
     65     build(tr[rt].r, mid + 1, r); 
     66 }
     67 
     68 void update(int &p, int x, int c, int l, int r)
     69 {
     70     if(!p) p = ++ num;
     71     tr[p].val += c;
     72     if(l == r) return ;
     73     int mid = l + r >> 1;
     74     if(x <= mid)
     75     update(tr[p].l, x, c, l, mid);
     76     else
     77     update(tr[p].r, x, c, mid + 1,r);
     78 }
     79 
     80 int lowbit(int x)
     81 {
     82     return x & (-x);
     83 }
     84 void update(int x, int y, int c)
     85 {
     86     for (; x < N; x += lowbit(x))
     87     {
     88         update(root[x], y, c, 1, n);
     89     }
     90 }
     91 
     92 int query(int p, int L, int R, int l, int r)
     93 {
     94     if(L <= l && R >= r)
     95     {
     96         return tr[p].val;
     97      } 
     98      int mid = l + r >> 1;
     99         int res = 0;
    100     if(L <= mid)
    101     res += query(tr[p].l, L, R, l, mid);
    102     if(R >  mid)
    103     res += query(tr[p].r, L, R, mid + 1, r);
    104     return res;     
    105 }
    106 
    107 int query(int x, int y, int L, int R)
    108 {
    109     int res = 0;
    110     for (; y; y -= lowbit(y))
    111         res += query(root[y], L, R, 1, n);
    112     for (; x; x -= lowbit(x))
    113         res -= query(root[x], L, R, 1, n);
    114     return res;
    115 }
    116 
    117 int main()
    118 {
    119     scanf("%d%d", &n, &m);
    120     for (int i = 1; i <= n; i ++)
    121     {
    122         scanf("%s",s);
    123         f[i] = t.insert(s);
    124     }
    125     t.dfs(0);
    126     build(root[0], 1, n);
    127     for (int i = 1; i <= n; i ++)
    128     {
    129         update(t.in[f[i]], i, 1);
    130         f[i] = t.in[f[i]];
    131     }
    132     while(m --)
    133     {
    134         int op;
    135         scanf("%d", &op);
    136         if(op == 1)
    137         {
    138             int l, r;
    139             scanf("%d%d", &l, &r);
    140             update(f[l], l, -1);
    141             update(f[r], r, -1);
    142             swap(f[l], f[r]);
    143             update(f[l], l, 1);
    144             update(f[r], r, 1);
    145         }
    146         else
    147         {
    148             int k, l, r;
    149             scanf("%s%d%d%d", s, &k, &l, &r);
    150             int pos = t.find(s, k);
    151             if(pos == -1)
    152             {
    153                 puts("0");
    154                 continue;
    155             }
    156             int L = t.in[pos] - 1, R = t.out[pos];
    157         //    cout << L << " " << R << endl;
    158             printf("%d
    ", query(L, R, l, r));
    159         }
    160     }
    161 } 
    View Code
  • 相关阅读:
    第 9 章 完成购物车
    新建 ASP.NET MVC 项目快速代码
    一个真正的应用程序(第7~8章)(所需代码在下一篇随笔里)
    HTML
    squid 高匿设置
    Linux操作系统上ADSL拨号上网的方法详解
    MYSQL-max_binlog_cache_size参数
    mysql查杀会话
    centos配置Tomcat以指定的身份(非root)运行
    mysql load data导入脚本
  • 原文地址:https://www.cnblogs.com/xwdzuishuai/p/12705916.html
Copyright © 2020-2023  润新知