#4021. 幸运字符串查询 (lucky)

题目描述

KC研究完了幸运数列,又开始对幸运字符串感兴趣(KC似乎不是个正常人)。幸运字符串是一个只包括 ‘4’ 和 ‘7’ 的字符串。现在KC手中有个长度为 N(1≤N≤106)N(1\le N\le 10^6)N(1≤N≤106) 的幸运字符串。天生调皮爱玩的KC开始玩起了这个字符串,他的玩法是每次从这个字符串中选定一段区间 [l,r][l,r][l,r] ,将这段区间上的所有 ‘4’ 换成 ‘7’,所有 ‘7’ 换成 ‘4’ 。

但是KC过了很久终于意识到自己玩的东西太无聊了,于是他找来你陪他玩,他会在变换玩若干区间后突然问你一个问题:当前这个幸运字符串的最长不降子序列的长度是多少?

现在给出 NNN 和 MMM ,以及KC手中原有的幸运字符串,MMM 为KC自己玩的次数加上询问你的次数,还有 MMM 次的信息。
输入格式

第一行包括 N,M(M≤300000)N,M(M\le 300000)N,M(M≤300000) 。

第二行是一个长度为 NNN 的幸运字符串。

接下来 MMM 行,每行一个操作信息,游戏中会按照给定的顺序执行操作。

switch l r表示KC对区间 [l,r][l,r][l,r] 进行了变换。
count表示KC向你提问了,你必须输出你的答案。
输出格式

每行对应一个count。
样例
样例输入 1

2 3
47
count
switch 1 2
count

样例输出 1

2
1

样例输入 2

3 5
747
count
switch 1 1
count
switch 1 3
count

样例输出 2

2
3
2

数据范围与提示

对于 30%30%30% 的数据 n,m≤1000n,m\le 1000n,m≤1000 。
题解:
因为只有两个字符,所以不减子序列只可能是4444444或4444477777或7777777
但题目又要支持反转,所以
4444444—>77777777
4444447777777—>777777774444444
7777777—>44444444
由此看来,还得记录一个77777777444444444
而答案就是前三个的最大值,
所以数据结构就呼之欲出了:
线段树!

#include
#include
#include
#include
#include
#define N 1000005
using namespace std;
int n,m,a[N];
struct segement
{
	int l,r,f1,f2,f3,f4;
	int lazy;
}t[N*4];//f1 4444 f2 444777 f3 777777 f4 7777744444
void build(int p,int l,int r){
	t[p].l=l;t[p].r=r;
	if(l==r){
		if(a[l]==4){
			t[p].f1++;
		}else{
			t[p].f3++;
	    }
	    return ;
	}
	int mid=(l+r)>>1;
	build(p*2,l,mid);build(p*2+1,mid+1,r);
	t[p].f2=max(max(t[p*2].f2,t[p*2].f1+t[p*2+1].f2),max(t[p*2+1].f2,t[p*2].f1+t[p*2+1].f3));
	t[p].f2=max(t[p].f2,t[p*2].f2+t[p*2+1].f3);
	t[p].f1=max(t[p*2].f1,max(t[p*2+1].f1,t[p*2].f1+t[p*2+1].f1));
	t[p].f3=max(t[p*2].f3,max(t[p*2+1].f3,t[p*2].f3+t[p*2+1].f3));
	t[p].f4=max(max(t[p*2].f4,t[p*2].f3+t[p*2+1].f4),max(t[p*2+1].f4,t[p*2].f3+t[p*2+1].f1));
	t[p].f4=max(t[p].f4,t[p*2].f4+t[p*2+1].f1);
}
void spread(int p){
	if(t[p].lazy&1){
		swap(t[p*2].f1,t[p*2].f3);
		swap(t[p*2].f2,t[p*2].f4);
        swap(t[p*2+1].f1,t[p*2+1].f3);
		swap(t[p*2+1].f2,t[p*2+1].f4);
		t[p*2].lazy+=t[p].lazy;
		t[p*2+1].lazy+=t[p].lazy;
		t[p].lazy=0;
	}
}
//f1 4444 f2 444777 f3 777777 f4 7777744444
void change(int p,int l,int r){
	if(t[p].l>=l&&t[p].r<=r){
        swap(t[p].f1,t[p].f3);
		swap(t[p].f2,t[p].f4);
        t[p].lazy+=1;
        return ;
	}
	spread(p);
    int mid=(t[p].l+t[p].r)>>1;
    if(l<=mid)change(p*2,l,r);
    if(r>mid)change(p*2+1,l,r);
    t[p].f2=max(max(t[p*2].f2,t[p*2].f1+t[p*2+1].f2),max(t[p*2+1].f2,t[p*2].f1+t[p*2+1].f3));
	t[p].f2=max(t[p].f2,t[p*2].f2+t[p*2+1].f3);
	t[p].f1=max(t[p*2].f1,max(t[p*2+1].f1,t[p*2].f1+t[p*2+1].f1));
	t[p].f3=max(t[p*2].f3,max(t[p*2+1].f3,t[p*2].f3+t[p*2+1].f3));
	t[p].f4=max(max(t[p*2].f4,t[p*2].f3+t[p*2+1].f4),max(t[p*2+1].f4,t[p*2].f3+t[p*2+1].f1));
	t[p].f4=max(t[p].f4,t[p*2].f4+t[p*2+1].f1);
}
int main()
{
	cin>>n>>m;
	string aa;
	cin>>aa;
	for(int i=1;i<=n;i++){
		if(aa[i-1]=='4')a[i]=4;
		else a[i]=7;
	}
	build(1,1,n);
	/*for(int i=1;i<=10;i++){
		cout<
	for(int i=1;i<=m;i++){
		cin>>aa;
		if(aa[0]=='s'){
			int x,y;cin>>x>>y;
			change(1,x,y);
		}else{
			cout<<max(t[1].f1,max(t[1].f2,t[1].f3))<<endl;
		}
	}
	return 0;
}

你可能感兴趣的:(测试,数据结构)