Codeforces Round #590 (Div. 3)

D. Distinct Characters Queries

Description

You are given a string ss consisting of lowercase Latin letters and qq queries for this string.

Recall that the substring s[l;r]s[l;r] of the string ss is the string slsl+1…srslsl+1…sr. For example, the substrings of "codeforces" are "code", "force", "f", "for", but not "coder" and "top".

There are two types of queries:

  • 1 pos c1 pos c (1≤pos≤|s|1≤pos≤|s|, cc is lowercase Latin letter): replace sposspos with cc (set spos:=cspos:=c);
  • 2 l r2 l r (1≤l≤r≤|s|1≤l≤r≤|s|): calculate the number of distinct characters in the substring s[l;r]s[l;r].

Input

The first line of the input contains one string ss consisting of no more than 105105 lowercase Latin letters.

The second line of the input contains one integer qq (1≤q≤1051≤q≤105) — the number of queries.

The next qq lines contain queries, one per line. Each query is given in the format described in the problem statement. It is guaranteed that there is at least one query of the second type.

output

For each query of the second type print the answer for it — the number of distinct characters in the required substring in this query.

Examples

Input

abacaba
5
2 1 4
1 4 b
1 5 b
2 4 6
2 1 7

Output

3
1
2

正确解法:

原本想着可修改的主席树来着,树状数组加上主席树。

改模板改了好久没过。

操作一:改变某个字符

操作二:统计区间【l,r】不同字符的个数。

有三种方法:

26个字母的树状数组:

每次需要for26次,统计这个字母是否在区间内。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <algorithm>
 5 #include <set>
 6 #include <queue>
 7 #include <stack>
 8 #include <string>
 9 #include <cstring>
10 #include <vector>
11 #include <map>
12 //#include <unordered_map>
13 #define mem( a ,x ) memset( a , x ,sizeof(a) )
14 #define rep( i ,x ,y ) for( int i = x ; i<=y ;i++ )
15 #define lson  l ,mid ,pos<<1
16 #define rson mid+1 ,r ,pos<<1|1
17 using namespace std;
18 typedef long long ll ;
19 typedef pair<int ,int> pii;
20 typedef pair<ll ,int> pli;
21 const int inf = 0x3f3f3f3f;
22 const int N = 1e5+100;
23 const ll mod =1e9+7 ;
24 char s[N],kkk;
25 int n,m;
26 int aa,bb,cc;
27 int bit[30][N];
28 int bitsize(int x)
29 {
30     return x&(-x);
31 }
32 void update(int k,int id,int x)
33 {
34     while(id<=n)
35     {
36         bit[k][id]+=x;
37         id+=bitsize(id);
38     }
39 }
40 int query(int k,int id)
41 {
42     int ans=0;
43     while(id>0)
44     {
45         ans+=bit[k][id];
46         id-=bitsize(id);
47     }
48     return ans;
49 }
50 int main()
51 {
52     scanf("%s",s+1);
53     n=strlen(s+1);
54     for(int i=1;i<=n;i++)
55     {
56         update(s[i]-‘a‘+1,i,1);
57     }
58     scanf("%d",&m);
59     while(m--)
60     {
61         scanf("%d",&aa);
62         if(aa==1)
63         {
64             scanf("%d %c",&bb,&kkk);
65             update(s[bb]-‘a‘+1,bb,-1);
66             s[bb]=kkk;
67             update(s[bb]-‘a‘+1,bb,1);
68         }
69         else
70         {
71             scanf("%d%d",&bb,&cc);
72             int ans=0,res;
73             for(int i=1;i<=26;i++)
74             {
75                 res=query(i,cc)-query(i,bb-1);
76                 if(res>0)   ans++;
77             }
78             printf("%d\n",ans);
79         }
80     }
81
82     return 0;
83 }

26个字母的线段树:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cmath>
  4 #include <algorithm>
  5 #include <set>
  6 #include <queue>
  7 #include <stack>
  8 #include <string>
  9 #include <cstring>
 10 #include <vector>
 11 #include <map>
 12 //#include <unordered_map>
 13 #define mem( a ,x ) memset( a , x ,sizeof(a) )
 14 #define rep( i ,x ,y ) for( int i = x ; i<=y ;i++ )
 15 #define lson  l ,mid ,pos<<1
 16 #define rson mid+1 ,r ,pos<<1|1
 17 using namespace std;
 18 typedef long long ll ;
 19 typedef pair<int ,int> pii;
 20 typedef pair<ll ,int> pli;
 21 const int inf = 0x3f3f3f3f;
 22 const int N = 1e5+100;
 23 const ll mod =1e9+7 ;
 24 char s[N],kkk;
 25 int n,m;
 26 int aa,bb,cc;
 27 int tree[30][4*N],ans[30],a[N];
 28 void push_up(int rt)
 29 {
 30     for(int i=1;i<=26;i++)
 31         tree[i][rt]=tree[i][rt<<1]+tree[i][rt<<1|1];
 32 }
 33 void build(int rt,int l,int r)
 34 {
 35     if(l==r)
 36     {
 37         tree[a[l]][rt]++;
 38         return;
 39     }
 40     int mid=l+r >>1;
 41     build(rt<<1,l,mid);
 42     build(rt<<1|1,mid+1,r);
 43     push_up(rt);
 44 }
 45 void update(int rt,int p,int x,int y,int l,int r)
 46 {
 47     if(l==r)
 48     {
 49         tree[x][rt]--;
 50         tree[y][rt]++;
 51         return;
 52     }
 53     int mid=l+r>>1;
 54     if(p<=mid)
 55         update(rt<<1,p,x,y,l,mid);
 56     else
 57         update(rt<<1|1,p,x,y,mid+1,r);
 58     push_up(rt);
 59 }
 60 void query(int l,int r,int rt,int L,int R)
 61 {
 62     if(r<=R&&L<=l)
 63     {
 64         for(int i=1;i<=26;i++)
 65             ans[i]+=tree[i][rt];
 66         return ;
 67     }
 68     int mid=l+r>>1;
 69     if(L<=mid)  query(l,mid,rt<<1,L,R);
 70     if(R>mid)   query(mid+1,r,rt<<1|1,L,R);
 71 }
 72 int main()
 73 {
 74     scanf("%s",s+1);
 75     n=strlen(s+1);
 76     for(int i=1;i<=n;i++)
 77         a[i]=s[i]-‘a‘+1;
 78     build(1,1,n);
 79     scanf("%d",&m);
 80     while(m--)
 81     {
 82         scanf("%d",&aa);
 83         if(aa==1)
 84         {
 85             scanf("%d %c",&bb,&kkk);
 86             update(1,bb,s[bb]-‘a‘+1,kkk-‘a‘+1,1,n);
 87             s[bb]=kkk;
 88         }
 89         else
 90         {
 91             scanf("%d%d",&bb,&cc);
 92             int sum=0;
 93             memset(ans,0,sizeof(ans));
 94             query(1,n,1,bb,cc);
 95             for(int i=1;i<=26;i++)
 96                 if(ans[i])
 97                     sum++;
 98             printf("%d\n",sum);
 99         }
100     }
101
102     return 0;
103 }

统计每个字母的下标。用set来快速删除加入元素。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <algorithm>
 5 #include <set>
 6 #include <queue>
 7 #include <stack>
 8 #include <string>
 9 #include <cstring>
10 #include <vector>
11 #include <map>
12 //#include <unordered_map>
13 #define mem( a ,x ) memset( a , x ,sizeof(a) )
14 #define rep( i ,x ,y ) for( int i = x ; i<=y ;i++ )
15 #define lson  l ,mid ,pos<<1
16 #define rson mid+1 ,r ,pos<<1|1
17 using namespace std;
18 typedef long long ll ;
19 typedef pair<int ,int> pii;
20 typedef pair<ll ,int> pli;
21 const int inf = 0x3f3f3f3f;
22 const int N = 1e5+100;
23 const ll mod =1e9+7 ;
24 char s[N],kkk;
25 int n,m;
26 int aa,bb,cc;
27 set<int>st[30];
28 set<int>::iterator it;
29 int main()
30 {
31     scanf("%s",s+1);
32     n=strlen(s+1);
33     for(int i=1;i<=n;i++)
34         st[s[i]-‘a‘+1].insert(i);
35     scanf("%d",&m);
36     while(m--)
37     {
38         scanf("%d",&aa);
39         if(aa==1)
40         {
41             scanf("%d %c",&bb,&kkk);
42             st[s[bb]-‘a‘+1].erase(bb);
43             s[bb]=kkk;
44             st[s[bb]-‘a‘+1].insert(bb);
45         }
46         else
47         {
48             scanf("%d%d",&bb,&cc);
49             int ans=0;
50             for(int i=1;i<=26;i++)
51             {
52                 it=st[i].lower_bound(bb);
53                 if(it==st[i].end()) continue;
54                 if((*it)<=cc)
55                     ans++;
56             }
57             printf("%d\n",ans);
58         }
59     }
60
61     return 0;
62 }

原文地址:https://www.cnblogs.com/Kaike/p/11617314.html

时间: 2024-10-07 12:37:01

Codeforces Round #590 (Div. 3)的相关文章

Codeforces Round #590 (Div. 3) Editorial

Codeforces Round #590 (Div. 3) Editorial 题目链接 官方题解 不要因为走得太远,就忘记为什么出发! Problem A 题目大意:商店有n件商品,每件商品有不同的价格,找出一个最小的可能值price,使得price * n >= sum,sum指的是原来商品价格的总和. 知识点:模拟 思路:求出sum/n向上取整即可,有两种方法.一是使用ceil()函数,但注意ceil()返回的是向上取整后的浮点数,所以要进行强制类型转换:二是直接向下取整,然后用if语句

Codeforces Round #590 (Div. 3) B2. Social Network (hard version)

链接: https://codeforces.com/contest/1234/problem/B2 题意: The only difference between easy and hard versions are constraints on n and k. You are messaging in one of the popular social networks via your smartphone. Your smartphone can show at most k most

Codeforces Round #590 (Div. 3) D. Distinct Characters Queries(线段树, 位运算)

链接: https://codeforces.com/contest/1234/problem/D 题意: You are given a string s consisting of lowercase Latin letters and q queries for this string. Recall that the substring s[l;r] of the string s is the string slsl+1-sr. For example, the substrings

Codeforces Round #590 (Div. 3) C. Pipes

链接: https://codeforces.com/contest/1234/problem/C 题意: You are given a system of pipes. It consists of two rows, each row consists of n pipes. The top left pipe has the coordinates (1,1) and the bottom right - (2,n). There are six types of pipes: two

Codeforces Round #590 (Div. 3)(e、f待补

https://codeforces.com/contest/1234/problem/A A. Equalize Prices Again 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 int main(){ 5 int n,a; 6 int t; 7 cin>>t; 8 ll sum = 0,ans; 9 while(t--){ 10 cin>>n;sum = 0

Codeforces Round #590 (Div. 3) F

传送门 题意: 给出一个只含前\(20\)个字符的字符串,现在可以选择一段区间进行翻转,问区间中字符各不相同时,最长长度为多少. 思路: 首先,容易将题意转换为选择两个字符各不相同的区间,然后长度相加取最大: 注意到字符串中满足条件的区间长度不超过\(20*n\),那么处理出所有区间,现在任务即为找到两个区间,其字符各不想同,且长度和最大: 因为最多\(20\)个字符,将满足条件的区间转换为二进制数,任务转换为找到两个数\(a_i,a_j\)满足\(a_i\&a_j=0\)且二进制为\(1\)的

Codeforces Round #590 (Div. 3)补题

要想上2000分,先刷几百道2000+的题再说 ---某神 题目 E F 赛时是否尝试 × × tag math bitmask 难度 2000 2400 状态 ? √ 解 E 待定 F 传送门 第一次接触状态压缩dp的题.这道题转换问题的思路非常巧妙. 原问题: 已知: 一个字符串,可进行不超过一次操作 操作限定: 选择某个子串,使其在原串中翻转 目的:使原串的特征值最大 串的特征值:串任意没有重复字符的子串,其包含字符的种类数 问题的转换: 首先选定一个子串a,之后再找到另一个子串b,使得a

Codeforces Round #590 (Div. 3) C——1234C Pipes

D. Distinct Characters Queries time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output You are given a system of pipes. It consists of two rows, each row consists of nn pipes. The top left pipe ha

Codeforces Round #428 (Div. 2)

Codeforces Round #428 (Div. 2) A    看懂题目意思就知道做了 #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i