CF145E Lucky Queries

CF145E Lucky Queries

英文题面不放了,直接上翻译:

题目描述

给你n个数,每个数是4或者7,给你m个任务完成

switch l r 把[l,r]位置的4换成7,7换成4

count 计算n个数的最长不下降子序列的长度

N个数的不下降子序列是这n个数移除掉0个或者若干个位置的数,并且满足从第2个数开始每一个数不小于前一个数的大小。

输入格式

第一行n,m

第二行n个数字

接下来m行每行一个命令

输出格式

对于每一个count的命令,输出n个数的最长不下降子序的长度

输入输出样例

输入样例#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

题解Here!

看到区间问题,线段树之类的肯定没得跑。
当然将$4,7$转成$0,1$应该都能想到。
不过怎样区间翻转是一个问题。
我们记录最长不上升子序列的长度和最长不下降子序列的长度,然后分别维护即可。
区间翻转的时候翻转一下就好。
那,维护怎么办?
其实最长不下降子序列只有一种情况:前面若干个$4$,后面若干个$7$。
那我们只要搞出分界点就好。
这里的分界点指的是最后一个$4$的位置。
而分界点只会在三个地方:左儿子区间$[l,mid-1]$中,$mid$,右儿子区间$[mid+1,r]$中。
于是分别计算长度,取最大值就好。
最长不上升子序列同理。
复杂度$O(m\log_2n)$。
代码还是挺好码的。
附代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#define LSON rt<<1
#define RSON rt<<1|1
#define FOUR(x) a[x].four
#define SEVEN(x) a[x].seven
#define SIGN(x) a[x].c
#define UPON(x) a[x].upon
#define DOWN(x) a[x].down
#define LSIDE(x) a[x].l
#define RSIDE(x) a[x].r
#define WIDTH(x) (RSIDE(x)-LSIDE(x)+1)
#define MAXN 1000010
using namespace std;
int n,m;
char ch[MAXN];
struct Segment_Tree{
	int seven,four,c,upon,down;
	int l,r;
}a[MAXN<<2];
inline int read(){
	int date=0,w=1;char c=0;
	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
	return date*w;
}
inline void pushup(int rt){
	FOUR(rt)=FOUR(LSON)+FOUR(RSON);
	SEVEN(rt)=SEVEN(LSON)+SEVEN(RSON);
	UPON(rt)=max(FOUR(LSON)+SEVEN(RSON),max(FOUR(LSON)+UPON(RSON),UPON(LSON)+SEVEN(RSON)));
	DOWN(rt)=max(SEVEN(LSON)+FOUR(RSON),max(SEVEN(LSON)+DOWN(RSON),DOWN(LSON)+FOUR(RSON)));
}
inline void pushdown(int rt){
	if(!SIGN(rt)||LSIDE(rt)==RSIDE(rt))return;
	SIGN(LSON)^=1;
	swap(FOUR(LSON),SEVEN(LSON));
	swap(UPON(LSON),DOWN(LSON));
	SIGN(RSON)^=1;
	swap(FOUR(RSON),SEVEN(RSON));
	swap(UPON(RSON),DOWN(RSON));
	SIGN(rt)=0;
}
void buildtree(int l,int r,int rt){
	LSIDE(rt)=l;RSIDE(rt)=r;SIGN(rt)=0;
	if(l==r){
		FOUR(rt)=(ch[l]=='4');
		SEVEN(rt)=(FOUR(rt)^1);
		UPON(rt)=DOWN(rt)=1;
		return;
	}
	int mid=l+r>>1;
	buildtree(l,mid,LSON);
	buildtree(mid+1,r,RSON);
	pushup(rt);
}
void update(int l,int r,int rt){
	if(l<=LSIDE(rt)&&RSIDE(rt)<=r){
		SIGN(rt)^=1;
		swap(FOUR(rt),SEVEN(rt));
		swap(UPON(rt),DOWN(rt));
		return;
	}
	pushdown(rt);
	int mid=LSIDE(rt)+RSIDE(rt)>>1;
	if(l<=mid)update(l,r,LSON);
	if(mid<r)update(l,r,RSON);
	pushup(rt);
}
void work(){
	int l,r;
	while(m--){
		scanf("%s",ch);
		if(ch[0]=='s'){
			l=read();r=read();
			update(l,r,1);
		}
		else printf("%d\n",UPON(1));
	}
}
void init(){
	n=read();m=read();scanf("%s",ch+1);
	buildtree(1,n,1);
}
int main(){
	init();
	work();
    return 0;
}

 

posted @ 2019-03-30 20:00  符拉迪沃斯托克  阅读(287)  评论(0编辑  收藏  举报
Live2D