• Codeforces 145E. Lucky Queries 线段树


    题目链接;

    题目描述:

    Petya loves lucky numbers very much. Everybody knows that lucky numbers are positive integers whose decimal record contains only the lucky digits 4 and 7. For example, numbers 47, 744, 4 are lucky and 5, 17, 467 are not.

    Petya brought home string s with the length of n. The string only consists of lucky digits. The digits are numbered from the left to the right starting with 1. Now Petya should execute m queries of the following form:

    • switch l r — "switch" digits (i.e. replace them with their opposites) at all positions with indexes from l to r, inclusive: each digit 4 is replaced with 7 and each digit 7 is replaced with (1 ≤ l ≤ r ≤ n);
    • count — find and print on the screen the length of the longest non-decreasing subsequence of string s.

    Subsequence of a string s is a string that can be obtained from s by removing zero or more of its elements. A string is called non-decreasing if each successive digit is not less than the previous one.

    Help Petya process the requests.

    Input

    The first line contains two integers n and m (1 ≤ n ≤ 106, 1 ≤ m ≤ 3·105) — the length of the string s and the number of queries correspondingly. The second line contains n lucky digits without spaces — Petya's initial string. Next m lines contain queries in the form described in the statement.

    Output

    For each query count print an answer on a single line.

    题意:给定由4和7组成的序列,有两个操作:(1) switch l f : 将区间[l,f]中的4变成7,7变成4    (2) count : 输出整个序列的最长上升子序列

    解题思路: 这是一道中规中矩的线段树的题,对于每个线段树的结点需要维护四个值:序列中4的数目num4,序列中7的数目num7,最长上升序列大小rise,最长下降序列大小down。 合并操作:对于每个区间合并,num4和num7就不用我说了,rise取 左区间的num4+右区间的rise 与 左区间的rise+右区间的num7中的最大值,同理 down取 左区间num7+右区间down 与 左区间down+右区间的num4的最大值。直接看代码吧。

    AC代码:

    #include<bits/stdc++.h>
    #define Mid ((l+r)>>1)
    #define lson (rt<<1)+1,l,Mid
    #define rson (rt<<1)+2,Mid+1,r
    #define ll (rt<<1)+1
    #define rr (rt<<1)+2
    using namespace std;
    const int MAX = 1000010;
    char str[MAX];
    
    struct Tree{
        int num4;
        int num7;
        int down;
        int rise;
    }seg[(MAX<<2)+1];
    int swi[(MAX<<2)+1];
    
    void pushup(int rt)
    {
        seg[rt].num4 = seg[ll].num4 + seg[rr].num4;
        seg[rt].num7 = seg[ll].num7 + seg[rr].num7;
        seg[rt].down = max(seg[ll].num7 + seg[rr].down, seg[ll].down + seg[rr].num4);
        seg[rt].rise = max(seg[ll].num4 + seg[rr].rise, seg[ll].rise + seg[rr].num7);
    }
    
    void build(int rt, int l, int r)
    {
        swi[rt] = 0;
        if(l == r)
        {
            if(str[l] == '4')
            {
                seg[rt].num4=seg[rt].rise=seg[rt].down = 1;
                seg[rt].num7=0;
                return ;
            }
            else
            {
                seg[rt].num7=seg[rt].rise=seg[rt].down=1;
                seg[rt].num4 = 0;
                return ;
            }
        }
        else
        {
            build(lson);
            build(rson);
            pushup(rt);
        }
    }
    
    void pushDown(int rt)
    {
        if(swi[rt] != 0)
        {
            swi[ll] += swi[rt];
            swi[rr] += swi[rt];
            if(swi[rt]&1)
            {
                swap(seg[ll].num4,seg[ll].num7);
                swap(seg[ll].rise,seg[ll].down);
                swap(seg[rr].num4,seg[rr].num7);
                swap(seg[rr].rise,seg[rr].down);
            }
            swi[rt] = 0;
        }
    }
    
    void update(int rt, int l, int r, int L, int R)
    {
        if(L <= l && R >= r)
        {
            swi[rt] += 1;
            swap(seg[rt].num4,seg[rt].num7);
            swap(seg[rt].rise,seg[rt].down);
        }
        else
        {
            pushDown(rt);
            if(L <= Mid)
                update(lson,L,R);
            if(R > Mid)
                update(rson,L,R);
            pushup(rt);
        }
    }
    
    int main()
    {
        int n,m;
        while(~scanf("%d %d",&n,&m))
        {
            scanf("%s",str);
            //memset(swi,0,sizeof(swi));
            build(0,0,n-1);
            char input[10];
            int l,r;
            for(int i=0; i<m; i++)
            {
                scanf("%s",input);
                if(input[0] == 's')
                {
                    scanf("%d %d",&l,&r);
                    update(0,0,n-1,l-1,r-1);
                }
                else
                {
                    printf("%d
    ",seg[0].rise);
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    python 包与模块
    互斥锁与自旋锁
    TCP三次握手四次挥手
    缓存击穿、缓存穿透、缓存雪崩
    五种IO模型
    MySQL使用mysqldump进行数据备份
    golang数据库连接池参数设置
    golang代码文件目录组织、包目录组织学习笔记
    【转】如何用Vim提高开发效率
    emacs显示行号
  • 原文地址:https://www.cnblogs.com/MyCodeLife-/p/8675738.html
Copyright © 2020-2023  润新知