• 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(mlog_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
    ",UPON(1));
    	}
    }
    void init(){
    	n=read();m=read();scanf("%s",ch+1);
    	buildtree(1,n,1);
    }
    int main(){
    	init();
    	work();
        return 0;
    }
    
  • 相关阅读:
    Android Watchdog
    Android Zygote进程是如何fork一个APP进程的
    java多线程面试题小结
    Java Socket通信以及可能出现的问题解决
    Java对象的浅拷贝和深拷贝&&String类型的赋值
    AtomicLong和LongAdder的区别
    JDK中Concurrent包介绍及使用(包含atomic包/lock包/并发容器/执行器)
    final关键字总结
    Java内存模型-final域的内存语义--没明白,预留以后继续理解
    synchronized底层实现原理&CAS操作&偏向锁、轻量级锁,重量级锁、自旋锁、自适应自旋锁、锁消除、锁粗化
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/10628714.html
Copyright © 2020-2023  润新知