zoukankan      html  css  js  c++  java
  • 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
     
  • 相关阅读:
    欧拉项目第十题;用筛法做,
    欧拉第十题 求2000000以内的素数之和
    求1000数字中13个相乘最大值
    筛法求10000以内的质数
    判断回文且寻找三位数乘三位数里最大的回文
    分解质因数
    输入一个正整数n,将其转换为二进制后输出。要求定义并调用函数dectobin(n),它的功能是输出
    hdu1863最小生成树krus模板&prim模板
    hdu 3870 最小割转化为最短路径2
    UVALive 3661 最小割转化为最短路径
  • 原文地址:https://www.cnblogs.com/Jessie-/p/9925710.html
Copyright © 2011-2022 走看看