题解 P2787 【语文1(chin1)- 理理思维】

SuperJvRuo

2018-10-05 14:52:45

Solution

用```std::set```实现的[珂朵莉树](https://www.luogu.org/blog/ACdreamer/chtholly-tree)才是正统,链表什么的都是异端。不会珂朵莉树的可以点前面的链接或者看本人在CF896C的题解。 ``` #include<cstdio> #include<cctype> #include<cstring> #include<set> int Read() { int x=0;char c=getchar(); while(!isdigit(c)) { c=getchar(); } while(isdigit(c)) { x=x*10+(c^48); c=getchar(); } return x; } struct node { int l,r; mutable char v; node(int L, int R=-1, char V=0):l(L), r(R), v(V) {} bool operator<(const node& o) const { return l < o.l; } }; using std::set; set<node> s; #define IT set<node>::iterator //split(pos)操作是指将原来含有pos位置的节点分成两部分:[l,pos−1][pos,r] IT split(int pos) { IT it = s.lower_bound(node(pos)); if (it != s.end() && it->l == pos) return it; --it; int L = it->l, R = it->r, V = it->v; s.erase(it); s.insert(node(L, pos-1, V)); return s.insert(node(pos, R, V)).first; } //暴力遍历区间查询 int count(int l,int r,char key) { IT itr=split(r+1),itl=split(l); int res=0; for(;itl!=itr;++itl) { if(itl->v==key) { res+=itl->r-itl->l+1; } } return res; } //珂朵莉树经典的区间赋值 void replace(int l,int r,char key) { IT itr=split(r+1),itl=split(l); s.erase(itl,itr); s.insert(node(l,r,key)); } //开个桶,遍历一遍然后insert进去 void sort_range(int l,int r) { int cnt[27]; memset(cnt,0,sizeof(cnt)); IT itr=split(r+1),itl=split(l); for(IT itl2=itl;itl2!=itr;++itl2) { cnt[itl2->v-'A']+=itl2->r-itl2->l+1; } s.erase(itl,itr); int pos=l; for(int i=0;i<26;++i) { if(cnt[i]) { s.insert(node(pos,pos+cnt[i]-1,i+'A')); pos+=cnt[i]; } } } char str[50005]; int main() { int n=Read(),m=Read(); scanf("%s",str+1); int cnt=1; char last=toupper(str[1]); for(int i=2;i<=n;++i) { str[i]=toupper(str[i]); if(str[i]==last) { ++cnt; } else { s.insert(node(i-cnt,i-1,last)); last=str[i]; cnt=1; } } s.insert(node(n+1-cnt,n,last)); s.insert(node(n+1,n+100,0)); int opt,x,y; char letter[5]; while(m--) { opt=Read(); if(opt==1) { x=Read(),y=Read(); scanf("%s",letter); printf("%d\n",count(x,y,toupper(letter[0]))); } else if(opt==2) { x=Read(),y=Read(); scanf("%s",letter); replace(x,y,toupper(letter[0])); } else { x=Read(),y=Read(); sort_range(x,y); } } return 0; } ```