CodeForces - 145E - Lucky Queries(线段树[区间合并])

标签: 线段树
122人阅读 评论(0) 收藏 举报
分类:

题意:

告诉你一个4和7 的序列

两种操作:

1. 讲区间的数反转(即4变7  7变4)

2。 输出总区间中   非递减子序列的长度。


思路:

注意:子序列是可以不连续的


很明显是线段树了。

统计4的长度。

统计7 的长度。

统计4开头 7结尾的长度。

然后就是简单的区间合并问题了。

因为涉及区间反转,所以 可以在开同样的变量 记录反转后 4 的长度, 反转后7的长度, 反转后47的长度。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;


const int maxn = 1000000 + 10;

struct node{
    int l,r;
    int len4[2], len7[2], len47[2];
    int ans;
    int rev;
    int len;
}nod[maxn<<2];

char s[maxn];
char cmd[20];

void pushup(int o){
    int lson = o << 1;
    int rson = o << 1 | 1;
    nod[o].len4[0] = nod[lson].len4[0] + nod[rson].len4[0];
    nod[o].len7[0] = nod[lson].len7[0] + nod[rson].len7[0];
    nod[o].len47[0] = 0;
    nod[o].len47[0] = max(nod[lson].len4[0] + nod[rson].len7[0], nod[o].len47[0]);
    nod[o].len47[0] = max(nod[lson].len4[0] + nod[rson].len47[0], nod[o].len47[0]);
    nod[o].len47[0] = max(nod[lson].len47[0] + nod[rson].len7[0], nod[o].len47[0]);
    nod[o].ans = 0;
    nod[o].ans = max(nod[o].ans, nod[o].len4[0]);
    nod[o].ans = max(nod[o].ans, nod[o].len7[0]);
    nod[o].ans = max(nod[o].ans, nod[o].len47[0]);


    ///========================


    nod[o].len4[1] = nod[lson].len4[1] + nod[rson].len4[1];
    nod[o].len7[1] = nod[lson].len7[1] + nod[rson].len7[1];
    nod[o].len47[1] = 0;
    nod[o].len47[1] = max(nod[lson].len4[1] + nod[rson].len7[1], nod[o].len47[1]);
    nod[o].len47[1] = max(nod[lson].len4[1] + nod[rson].len47[1], nod[o].len47[1]);
    nod[o].len47[1] = max(nod[lson].len47[1] + nod[rson].len7[1], nod[o].len47[1]);
}


void deal(int o){
    nod[o].rev ^= 1;
    swap(nod[o].len4[0], nod[o].len4[1]);
    swap(nod[o].len7[0], nod[o].len7[1]);
    swap(nod[o].len47[0], nod[o].len47[1]);
    nod[o].ans = 0;
    nod[o].ans = max(nod[o].ans, nod[o].len4[0]);
    nod[o].ans = max(nod[o].ans, nod[o].len7[0]);
    nod[o].ans = max(nod[o].ans, nod[o].len47[0]);
}
void pushdown(int o){

    if (nod[o].rev){
        deal(o<<1);
        deal(o<<1|1);
        nod[o].rev = 0;
    }
}

void build(int l,int r,int o){
    nod[o].l = l;
    nod[o].r = r;
    nod[o].rev = 0;
    nod[o].len = r - l + 1;
    if (l == r){
        if (s[l] == '4'){
            nod[o].len4[0] = 1;
            nod[o].len7[0] = 0;
            nod[o].len47[0] = 0;

            nod[o].len4[1] = 0;
            nod[o].len7[1] = 1;
            nod[o].len47[1] = 0;
            nod[o].ans = 1;
            return;
        }
        else {
            nod[o].len4[0] = 0;
            nod[o].len7[0] = 1;
            nod[o].len47[0] = 0;

            nod[o].len4[1] = 1;
            nod[o].len7[1] = 0;
            nod[o].len47[1] = 0;
            nod[o].ans = 1;
            return;
        }
    }


    int m = l + r >> 1;
    build(l, m, o << 1);
    build(m+1, r, o<<1|1);
    pushup(o);
}



void update(int L,int R,int l,int r,int o){
    if (L <= l && r <= R){
        deal(o);
        return;
    }
    pushdown(o);

    int m = l + r >> 1;
    if (m >= L){
        update(L, R, l, m, o<<1);
    }
    if (m < R){
        update(L, R, m+1, r, o<<1|1);
    }
    pushup(o);
}



int main(){

    int n,q;
    scanf("%d %d", &n, &q);

    scanf("%s", s+1);
    build(1, n, 1);

    while(q--){
        scanf("%s", cmd);
        if (cmd[0] == 'c'){
            printf("%d\n", nod[1].ans);
        }
        else {
            int x,y;
            scanf("%d %d", &x, &y);
            update(x, y, 1, n, 1);
        }
    }



    return 0;
}

E. Lucky Queries
time limit per test
3 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

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 477444 are lucky and 517467 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 4 (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.

Examples
input
2 3
47
count
switch 1 2
count
output
2
1
input
3 5
747
count
switch 1 1
count
switch 1 3
count
output
2
3
2
Note

In the first sample the chronology of string s after some operations are fulfilled is as follows (the sought maximum subsequence is marked with bold):

  1. 47
  2. 74
  3. 74
In the second sample:
  1. 747
  2. 447
  3. 447
  4. 774
  5. 774


查看评论

codeforces 145E Lucky Queries

codeforces 145E Lucky Queries
  • k_l_c_
  • k_l_c_
  • 2016-07-24 14:28:41
  • 559

codeforces 145E - Lucky Queries

题目大意:给一个长度为n的47序列(就是只有4和7),两种操作: 操作1:count 要求输出当前数列的最长非下降子序列(注意是子序列,不是子串。。。一开始没看清题WA半天)。 操作2 : swi...
  • dyx404514
  • dyx404514
  • 2013-03-14 16:24:36
  • 908

Educational Codeforces Round 23 A-F

感觉这种比赛就是拼手速啊QwQ A.Treasure Hunt 题目大意:平面直角坐标系中给定起点和终点,每次可以从(a,b)走向(a+x,b+y),(a-x,b-y),(a+x,b-y),(a-...
  • Mys_C_K
  • Mys_C_K
  • 2017-06-16 11:32:16
  • 229

线段树专题—POJ 3667 Hotel(区间合并模板)

题意:给一个n和m,表示n个房间,m次操作,操作类型有2种,一种把求连续未租出的房间数有d个的最小的最左边的房间号,另一个操作时把从x到x+d-1的房间号收回。 分析:这是一个区间合并的典型...
  • sin_XF
  • sin_XF
  • 2015-08-15 14:47:53
  • 907

Educational Codeforces Round 23 F. MEX Queries(线段树区间设值)

题意:一个无限长的序列,q次操作,有三种操作: 1 l r : 将区间[l, r]设为1 2 l r : 将区间[l, r]设为0 3 l r : 将区间[l, r]的数反转(0变1, 1变0)...
  • CillyB
  • CillyB
  • 2017-10-08 13:27:04
  • 138

线段树—区间合并

线段树的区间合并,即寻找询问区间中满足条件的连续最长区间。 而一个区间连续的最长区间有两种情况: 1、此连续最长区间全在左子树或全在右子树,则sum[t]=max(sum[t 2、一部分在左子树...
  • night0508
  • night0508
  • 2016-08-04 21:24:50
  • 1592

线段数练习一: CF145E E. Lucky Queries

E. Lucky Queries time limit per test 3 seconds memory limit per test 256 megabytes input stand...
  • NOI2015
  • NOI2015
  • 2015-01-29 16:38:47
  • 259

线段树区间更新+区间合并

题目链接 一看就是线段树区间合并的题。 俩操作,一个跟新,一个查询#include #include #include #include #include #include #include #i...
  • nucshiyilang
  • nucshiyilang
  • 2017-05-22 10:52:46
  • 88

Educational Codeforces Round 23 F. MEX Queries(离散化+线段树)

题目链接:http://codeforces.com/contest/817/problem/F 这个题的难度不像是F啊。。。 然而 我好蠢啊。。。 最开始发现,其实很多区间可以合并在...
  • sinat_32872703
  • sinat_32872703
  • 2017-06-17 20:36:46
  • 293

POJ Hotel (线段树--区间合并[区间赋值])

题意: n间空房子, 操作1问你能否连续住x 个房子, 如果能 就输出最左边的编号。 如果不能输出0; 操作2 将给定的区间[x,y] 清空。 思路: 线段树区间合并。 像极了HDU 154...
  • aozil_yang
  • aozil_yang
  • 2017-06-20 22:06:18
  • 264
    个人资料
    持之以恒
    等级:
    访问量: 21万+
    积分: 7914
    排名: 3296
    文章分类
    最新评论