CF上给的标签是数据结构。但给的题解里的方法是很巧的暴力,用vector
先看题解的方法。
1 #include2 #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 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< endl; 47 } 48 } 49 return 0; 50 }
然而我看别人线段树的代码没看懂。
但巧了我又去补了道 POJ - 2777
立马发现这两题有异曲同工之处。
POJ的题意是给线段染色,起始一种颜色,区间染色,最多30种颜色,询问区间中有几种颜色。应该是用了bitmask,用不同的位代表不同的颜色,每位上1代表存在这样的颜色,最后对所询问区间内按位或,再统计几位为1就为答案。
还要求你支持区间修改,这CF上这题只有要求单点更新的,很显然我们也可以用不同的位上的1代表不同的字母,最后将区间内的值按位或即可,最后统计有几位为1,就是这个区间几个不同的字母。
下见代码该题线段树解法。
1 #include2 #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< - 1<
- 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<
endl; 88 } 89 } 90 return 0; 91 }