P2787 语文1(chin1)- 理理思维(线段树)

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2787 语文1(chin1)- 理理思维(线段树)相关的知识,希望对你有一定的参考价值。

P2787 语文1(chin1)- 理理思维(线段树)

  • 对每个字母开一棵线段树
  • 操作1就是区间查询
  • 操作2就是区间修改
  • 操作3可以看成 先预处理查询出区间对应的每个字母的个数,然后进行区间修改。
  • 然后没了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=5e4+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define x first
#define y second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
#define ios ios::sync_with_stdio(false),cin.tie(nullptr) 
void Print(int *a,int n){
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\\n",a[n]); 
}
//区间修改 区间求和
#define il inline 
#define lx x<<1
#define rx x<<1|1
#define len(x) (a[x].r-a[x].l+1)
char str[N];
struct SegTree{
	struct node{
	int l,r,lz;
	int s;
	}a[N<<2];
	il void re(int x){ a[x].s=a[lx].s+a[rx].s; }
	il void ptg(int x,int y){
		a[x].lz=y;
		if(y==1) a[x].s=len(x);
		else a[x].s=0;
	}
	il void pd(int x){
		if(a[x].lz){
			ptg(lx,a[x].lz),ptg(rx,a[x].lz);
			a[x].lz=0;
		}
	}
	il void bud(int x,int l,int r,char ch){
		a[x].l=l,a[x].r=r;
		if(l==r){
			a[x].s=(str[l]==ch);
			return;
		}
		int m=(l+r)>>1;bud(lx,l,m,ch),bud(rx,m+1,r,ch);
		re(x);
	}
	il void upd(int x,int l,int r,int val){
		if(a[x].lz==val) return;
		if(a[x].l>=l&&a[x].r<=r){
			ptg(x,val);return;
		}
		pd(x);
		int m=(a[x].l+a[x].r)>>1;
		if(l<=m) upd(lx,l,r,val);
		if(r>m) upd(rx,l,r,val);
		re(x);
	}
	il int que(int x,int l,int r){
		if(!a[x].s) return 0;
		if(a[x].l>=l&&a[x].r<=r) return a[x].s;
		pd(x);
		int m=(a[x].l+a[x].r)>>1;int ans=0;
		if(l<=m) ans+=que(lx,l,r);
		if(r>m) ans+=que(rx,l,r);
		return ans;
	}
}T[26];
int tmp[26];
int main(){
	int n,m;scanf("%d%d%s",&n,&m,str+1);
	rep(i,1,n) str[i]=toupper(str[i]);
	for(int i=0;i<26;i++) T[i].bud(1,1,n,'A'+i);
	while(m--){
		int op,l,r;scanf("%d%d%d",&op,&l,&r);
		char ch;
		if(op==1){
			scanf("\\n%c",&ch);ch=toupper(ch);
			printf("%d\\n",T[ch-'A'].que(1,l,r));
		}else if(op==2){
			scanf("\\n%c",&ch);ch=toupper(ch);
			for(char i='A';i<='Z';++i){
				if(ch==i) T[i-'A'].upd(1,l,r,1);
				else T[i-'A'].upd(1,l,r,2);
			}
		}else {
			for(int i=0;i<26;i++){
				tmp[i]=T[i].que(1,l,r);
				T[i].upd(1,l,r,2);
			}
			for(int i=0;i<26;i++){
				if(tmp[i])T[i].upd(1,l,l+tmp[i]-1,1),l+=tmp[i];
			}			
		}
	}
	return 0;
}

以上是关于P2787 语文1(chin1)- 理理思维(线段树)的主要内容,如果未能解决你的问题,请参考以下文章

P2787 语文1(chin1)- 理理思维

P2787 语文1(chin1)- 理理思维(珂朵莉树)

语文1(chin1)- 理理思维

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

P3842 [TJOI2007]线段 思维 ,DP

语文 散文阅读