2018.11.07-1015-幸运字符串查询 (lucky)

题目描述:

KC研究完了幸运数列,又开始对幸运字符串感兴趣(KC似乎不是个正常人)。幸运字符串是一个只包括'4'和'7'的字符串。现在KC手中有个长度为N(1<=N<=1,000,000)的幸运字符串。天生调皮爱玩的KC开始玩起了这个字符串,他的玩法是每次从这个字符串中选定一段区间[l,r],将这段区间上的所有'4'换成'7',所有'7'换成'4'。
但是KC过了很久终于意识到自己玩的东西太无聊了,于是他找来你陪他玩,他会在变换玩若干区间后突然问你一个问题:当前这个幸运字符串的最长不降子序列的长度是多少?
现在给出N和M,以及KC手中原有的幸运字符串,M为KC自己玩的次数加上询问你的次数,还有M次的信息。

输入:

第一行包括N,M,M<=300,000.
第二行是一个长度为N的幸运字符串。
接下来M行,每行一个操作信息,游戏中会按照给定的顺序执行操作。。
switch l r表示KC对区间[l,r]进行了变换。
count表示KC向你提问了,你必须输出你的答案。

输出:

每行对应一个count。

算法标签:线段树

线段树是万能的小声bb

思路:

考虑每个不下降序列只能有单个4或者单个7或者前一段4和后一段7组成,于是我们维护每个序列里4的个数,7的个数,以及连续一段4连接一段7,以及连续一段7再一段4的个数。

觉得自己的代码非常简单易懂,再小声bb

以下代码:

#include<bits/stdc++.h>
#define il inline
#define _(d) while(d(isdigit(ch=getchar())))
using namespace std;
const int N=1e6+5;
char ss[10];
int n,m,a[N],_4[N<<2],_7[N<<2],_47[N<<2],_74[N<<2],rev[N<<2];
il int read(){int x;char ch;_(!);x=ch^48;_()x=(x<<1)+(x<<3)+(ch^48);return x;}
il int r(){int x;char ch;_(!);x=ch^48;return x;}
il void update(int x){
    _4[x]=_4[x<<1]+_4[x<<1|1];_7[x]=_7[x<<1]+_7[x<<1|1];
    _47[x]=max(_4[x<<1]+_7[x<<1|1],_4[x<<1]+_47[x<<1|1]);
    _47[x]=max(_47[x],_47[x<<1]+_7[x<<1|1]);
    _74[x]=max(_7[x<<1]+_4[x<<1|1],_74[x<<1]+_4[x<<1|1]);
    _74[x]=max(_74[x],_7[x<<1]+_74[x<<1|1]);
}
il void pushdown(int x){
    if(!rev[x])return;
    swap(_4[x<<1],_7[x<<1]);swap(_47[x<<1],_74[x<<1]);rev[x<<1]^=1;rev[x]=0;
    swap(_4[x<<1|1],_7[x<<1|1]);swap(_47[x<<1|1],_74[x<<1|1]);rev[x<<1|1]^=1;
}
il void build(int x,int l,int r){
    if(l==r){if(a[l]==4)_4[x]=1;else _7[x]=1;return;}
    int mid=(l+r)>>1;
    build(x<<1,l,mid);build(x<<1|1,mid+1,r);
    update(x);
}
il void change(int x,int l,int r,int ql,int qr){
    if(ql<=l&&r<=qr){
        swap(_4[x],_7[x]);swap(_47[x],_74[x]);rev[x]^=1;return;
    }
    int mid=(l+r)>>1;pushdown(x);
    if(ql<=mid)change(x<<1,l,mid,ql,qr);
    if(mid<qr)change(x<<1|1,mid+1,r,ql,qr);
    update(x);
}
int main()
{
    n=read();m=read();for(int i=1;i<=n;i++)a[i]=r();
    build(1,1,n);
    while(m--){
        scanf(" %s",ss);
        if(ss[0]=='c'){
            printf("%d
",max(_4[1],max(_7[1],_47[1])));
        }
        if(ss[0]=='s'){
            int x=read(),y=read();change(1,1,n,x,y);
        }
    }
  return 0;
}
View Code
 
原文地址:https://www.cnblogs.com/Jessie-/p/9925710.html