2019南京ICPC(重现赛) F - Paper Grading

题目链接: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\n", query(L, R, l, r));
159         }
160     }
161 } 

原文地址:https://www.cnblogs.com/xwdzuishuai/p/12705916.html

时间: 2024-08-30 14:32:36

2019南京ICPC(重现赛) F - Paper Grading的相关文章

2019 ICPC Asia Nanjing Regional F. Paper Grading

题目链接:https://nanti.jisuanke.com/t/42400 题意:给一个模式串集合,序号1~n,有T个操作,或者是交换序号,或者是查询模式串集合中序号在L到R之 间的字符串有多少个和目标串公共前缀长度大于等于K. --------------------------------- 对模式串集合建字典树,则与目标串\(LCP\)大于等K的字符串,都在以目标串第\(K\)个字符所在的结点为根的子树中,每个模式串插入字典树的过程中记录序号,修改时交换序号,询问就相于在子树中询问有多

【2019.07.04】2018南京icpc现场赛

补题地址:https://www.jisuanke.com/contest/1847?view=challenges A:? B CDEF G:? HI:?J:? KLM 原文地址:https://www.cnblogs.com/ncu2019/p/11142346.html

2018南京icpc现场赛心得

第一次参加icpc的比赛,也是第一块奖牌,虽然只是铜,但其实打的已经很好了,稍微差一点就可以摸银了. 之前参加省赛,成为那次比赛我校唯一一个没拿奖的队伍,其实还是一直都有一些心结的,而这段时间和新的队友的组队,虽然新队员的实力比之前的队友抢了很多,但是总感觉配合一直有问题,在比赛前一天的晚上,睡在一个房间里聊了很多话,也算是和队友真正达成了默契吧,所以第二天的现场赛配合的很好. 但是我自己在最近一段时间由于各种原因,其实个人的训练远没有之前那么多了,希望接下来能调整自己的训练,争取能在青岛站给奖

2019南昌icpc网络赛 I题 分块套BIT

https://nanti.jisuanke.com/t/41356 对于带修的二维数点,可以bit套主席树,也可CDQ三维偏序 但是最后我选择分块套BIT暴力... 复杂度为$m(blocksize*logn+blocknum)$ 显然,如果按照$\sqrt{n}$分块,并不是最优的 我们可以适当的增加块的大小,减少块的数量,让$blocksize*logn=blocknum$ 在这个题中,大概就是$\sqrt{1e6}$到$\sqrt{2e6}$之间吧 #include<bits/stdc+

2019上海icpc网络赛B. Light bulbs(思维+差分)

题目传送门 题意 T组案例,每组案例:n个灯泡(from 0 to n-1),m次操作,每次操作把区间[L,R]内的灯泡翻转(开变关,关变开),问m次操作之后有多少灯泡是亮着的.(时间限制:1000ms  内存限制:8192K) 题解 这道题不仅卡时间,更是卡内存,所以用线段树会爆内存 正解: 该题可以转换为经典的差分问题:每次操作对[L,R]的所有数进行+1操作,求最后有多少个奇数.(设该数组为a[n],每次操作a[L]+1,a[R+1]-1,求前缀和sum[i]=sum[i-1]+a[i]即

2019年湘潭大学程序设计竞赛(重现赛)

2019年湘潭大学程序设计竞赛(重现赛) A:Who's better? #include<bits/stdc++.h> using namespace std; int main(){ int n1,p1,s1,n2,p2,s2; cin>>n1>>p1>>s1; cin>>n2>>p2>>s2; if(n1!=n2){ if(n1>n2)cout<<"1\n"; else cout

hdu5512 Pagodas(2015ACM/ICPC亚洲区沈阳站-重现赛(感谢东北大学) )

Pagodas Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 14 Accepted Submission(s): 13 Problem Description n pagodas were standing erect in Hong Jue Si between the Niushou Mountain and the Yuntai M

2017 acm / icpc shenyang 双十一单身狗温馨重现赛

上午做实验老师看错时间来晚了,20与非门一侧坏掉..于是做完实验就,光荣迟到了!!!QAQ... 一开始..看B题...喵喵喵??? J题...窝只会暴力..算了算了.. 刷新~ I题AC ratio 好像还可以!戳进去一看,a+b+c+d...一克斯Q斯咪?哭叽叽写了个大数加法,piapiapia乱敲一气竟然没崩,AC~~~是个好开头吖有木有~o(* ̄▽ ̄*)ブ~ K题就是小兔子跳啊跳~piapiapia求和然后选择一下从哪一端起跳,紫欣sama1A~ L题一开始对题意有误解,看懂样例之后就发

2017ACM/ICPC亚洲区沈阳站-重现赛(感谢东北大学)HDU6225.Little Boxes-大数加法

整理代码... Little Boxes Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 2304    Accepted Submission(s): 818 Problem Description Little boxes on the hillside.Little boxes made of ticky-tacky.Littl