Codeforces Round #590 D. Distinct Characters Queries

CF上给的标签是数据结构。但给的题解里的方法是很巧的暴力,用vector<set>维护每个字母出现的下标,每次修改加下标,擦下标。每次询问对每个字母分别lower_bound查找区间内是否存在这样位置,实在太妙了!

先看题解的方法。

 1 #include <bits/stdc++.h>
 2 #define debug(x) cout << #x << ": " << x << endl
 3 using namespace std;
 4 typedef long long ll;
 5 const int MAXN=2e5+7;
 6 const int INF=0x3f3f3f3f;
 7 
 8 int main()
 9 {
10     ios::sync_with_stdio(false);
11     cin.tie(0);
12     string s;
13     cin>>s;
14     vector<set<int> > alp(26);
15     for(int i=0;i<s.size();++i)
16     {
17         alp[s[i] - 'a'].insert(i);
18     }
19     int q;
20     cin>>q;
21     while(q--)
22     {
23         int op;
24         cin>>op;
25         if(op==1)
26         {
27             int pos;
28             char c;
29             cin>>pos>>c;
30             --pos;
31             alp[s[pos]-'a'].erase(pos);
32             s[pos]=c;
33             alp[s[pos]-'a'].insert(pos);
34         }
35         else
36         {
37             int l,r;
38             cin>>l>>r;
39             --l,--r;
40             int cnt=0;
41             for(int i=0;i<26;++i)
42             {
43                 auto k=alp[i].lower_bound(l);
44                 if(k!=alp[i].end() && *k<=r) cnt++;
45             }
46             cout<<cnt<<endl;
47         }
48     }
49     return 0;
50 }

然而我看别人线段树的代码没看懂。

但巧了我又去补了道 POJ - 2777

立马发现这两题有异曲同工之处。

POJ的题意是给线段染色,起始一种颜色,区间染色,最多30种颜色,询问区间中有几种颜色。应该是用了bitmask,用不同的位代表不同的颜色,每位上1代表存在这样的颜色,最后对所询问区间内按位或,再统计几位为1就为答案。

还要求你支持区间修改,这CF上这题只有要求单点更新的,很显然我们也可以用不同的位上的1代表不同的字母,最后将区间内的值按位或即可,最后统计有几位为1,就是这个区间几个不同的字母。

下见代码该题线段树解法。

 1 #include <iostream>
 2 #define debug(x) cout << #x << ": " << x << endl
 3 #define lson (rt<<1)
 4 #define rson (rt<<1|1)
 5 #define Lson l,m,lson
 6 #define Rson m+1,r,rson
 7 using namespace std;
 8 typedef long long ll;
 9 const int MAXN=1e5+7;
10 const int INF=0x3f3f3f3f;
11 int seg[MAXN<<2],lazy[MAXN<<2];
12 string s;
13 
14 inline void pushup(int rt){seg[rt]=(seg[lson]|seg[rson]);}
15 
16 void pushdown(int rt)
17 {
18     if(lazy[rt])
19     {
20         seg[lson]=seg[rson]=lazy[rt];
21         lazy[lson]=lazy[rson]=lazy[rt];
22         lazy[rt]=0;
23     }
24 }
25 
26 void build(int rt,int l,int r)
27 {
28     if(l==r) {seg[rt]=1<<(s[l-1]-'a');return;}
29     int mid=l+r>>1;
30     build(lson,l,mid);
31     build(rson,mid+1,r);
32     pushup(rt);
33 }
34 
35 void update(int rt,int l,int r,int L,int R,int item)
36 {
37     if(l>=L && r<=R) {seg[rt]=1<<item;lazy[rt]=1<<item;return;}
38     int mid=l+r>>1;
39     pushdown(rt);
40     if(L<=mid) update(lson,l,mid,L,R,item);
41     if(R>mid) update(rson,mid+1,r,L,R,item);
42     pushup(rt);
43 }
44 
45 int query(int rt,int l,int r,int L,int R)
46 {
47     if(l>=L && r<=R){return seg[rt];}
48     int mid=l+r>>1;
49     pushdown(rt);
50     int ans1=0,ans2=0,ans=0;
51     if(L<=mid) ans1=query(lson,l,mid,L,R);
52     if(R>mid) ans2=query(rson,mid+1,r,L,R);
53     ans=ans1|ans2;
54     return ans;
55 
56 }
57 int main()
58 {
59     ios::sync_with_stdio(false);
60     cin.tie(0);
61     int q;
62     cin>>s>>q;
63     int n=s.size();
64     build(1,1,n);
65     while(q--)
66     {
67         int op;
68         cin>>op;
69         if(op==1)
70         {
71             int p;
72             string z;
73             cin>>p>>z;
74             int x=z[0]-'a';
75             update(1,1,n,p,p,x);
76         }
77         else if(op==2)
78         {
79             int L,R;
80             cin>>L>>R;
81             int cnt=0,ans=query(1,1,n,L,R);
82             while(ans)
83             {
84                 if(ans&1) cnt++;
85                 ans>>=1;
86             }
87             cout<<cnt<<endl;
88         }
89     }
90     return 0;
91 }
View Code

猜你喜欢

转载自www.cnblogs.com/Zzqf/p/11628734.html