洛谷P2253 好一个一中腰鼓!

题目背景

话说我大一中的运动会就要来了,据本班同学剧透(其实早就知道了),我萌萌的初二年将要表演腰鼓[喷],这个无厘头的题目便由此而来。

Ivan乱入:“忽一人大呼:‘好一个安塞腰鼓!’满座寂然,无敢哗者,遂与外人间隔。”

题目描述

设想一下,腰鼓有两面,一面是红色的,一面是白色的。初二的苏大学神想给你这个oier出一道题。假设一共有N(1<=N<=20,000)个同学表演,表演刚开始每一个鼓都是红色面朝向观众,舞蹈老师会发出M(1<=M<=20,000)个指令,如果指令发给第i个表演的同学,这位同学就会把腰鼓反过来,如果腰鼓之前是红色面朝向观众的,那么就会变成白色面朝向观众,反之亦然。那么问题来了(!?),在老师每一次发出指令后,找到最长的连续的一排同学,满足每相邻的两个手中的腰鼓朝向观众的一面互不相同,输出这样一排连续的同学的人数。

输入输出格式

输入格式:

第一行有两个整数, 分别为表演的同学总数N, 和指令总数M。

之后M行, 每行有一个整数i: 1<=i<=N, 表示舞蹈老师发出的指令。

输出格式:

输出有M行, 其中每i行有一个整数.

表示老师的第i条指令发出之后, 可以找到的满足要求的最长连续的一排表演同学有多长?

输入输出样例

输入样例#1:

6 2
2
4

输出样例#1:

3
5

说明

Huangc温馨提示:其实数据根本没你想象的那么大。。。[坏笑]、、

分析:一类线段树的经典题型,这种题和求最长相同颜色区间的做法是差不多的,都是要用线段树解决,那么要记录哪些信息呢?满足要求的区间长度是肯定要记录的,还要记录每一个区间左端点和右端点的颜色,仅仅用这些信息还不能更新区间长度,还要记录每个区间从左向右最多能扩展多少,从右向左能扩展多少,这样就能求出答案来。

合并是一个难点,当前区间的答案可能是左区间的答案也可能是右区间的答案也可能是左右中间合并的答案,在合并的时候判断一下左右端点的颜色是否相同就好了.同时还要更新向右延伸的最大长度和向左延伸的最大长度.

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>

using namespace std;

int n,m,lnum[200010],rnum[200010],lc[200010],rc[200010],ans[200010];

void pushup(int o,int len)
{
    lnum[o] = lnum[o * 2];
    rnum[o] = rnum[o * 2 + 1];
    lc[o] = lc[o * 2];
    rc[o] = rc[o * 2 + 1];
    ans[o] = max(max(lnum[o * 2],max(rnum[o * 2 + 1],max(rnum[o * 2],lnum[o * 2 + 1]))),max(ans[o * 2],ans[o * 2 + 1]));
    if (rc[o * 2] != lc[o * 2 + 1])
    {
        ans[o] = max(ans[o],rnum[o * 2] + lnum[o * 2 + 1]);
        if (lnum[o * 2] == (len - (len >> 1)))
        lnum[o] += lnum[o * 2 + 1];
        if (rnum[o * 2 + 1] == (len >> 1))
        rnum[o] += rnum[o * 2];
    }
}

void build(int l,int r,int o)
{
    if (l == r)
    {
        lnum[o] = rnum[o] = ans[o] = 1;
        lc[o] = rc[o] = 0;
        return;
    }
    int mid = (l + r) >> 1;
    build(l,mid,o * 2);
    build(mid + 1,r,o * 2 + 1);
    pushup(o,r - l + 1);
}

void update(int l,int r,int o,int v)
{
    if (l == r)
    {
        lc[o] = rc[o] = (lc[o] + 1) % 2;
        return;
    }
    int mid = (l + r) >> 1;
    if (v <= mid)
    update(l,mid,o * 2,v);
    else
    update(mid + 1,r,o * 2 + 1,v);
    pushup(o,r - l + 1);
}

int main()
{
    scanf("%d%d",&n,&m);
    build(1,n,1);
    for (int i = 1; i <= m; i++)
    {
        int t;
        scanf("%d",&t);
        update(1,n,1,t);
        printf("%d\n",ans[1]);
    }

    return 0;
}
时间: 2024-10-07 11:30:49

洛谷P2253 好一个一中腰鼓!的相关文章

洛谷 P2253 好一个一中腰鼓 --线段树

P2253 好一个一中腰鼓 --线段树 题目背景 话说我大一中的运动会就要来了,据本班同学剧透(其实早就知道了),我萌萌的初二年将要表演腰鼓[喷],这个无厘头的题目便由此而来. Ivan乱入:“忽一人大呼:‘好一个安塞腰鼓!’满座寂然,无敢哗者,遂与外人间隔.” 题目描述 设想一下,腰鼓有两面,一面是红色的,一面是白色的.初二的苏大学神想给你这个oier出一道题.假设一共有N(1<=N<=20,000)个同学表演,表演刚开始每一个鼓都是红色面朝向观众,舞蹈老师会发出M(1<=M<=

洛谷 P2253 好一个一中腰鼓!

题目背景 话说我大一中的运动会就要来了,据本班同学剧透(其实早就知道了),我萌萌的初二年将要表演腰鼓[喷],这个无厘头的题目便由此而来. Ivan乱入:“忽一人大呼:‘好一个安塞腰鼓!’满座寂然,无敢哗者,遂与外人间隔.” 题目描述 设想一下,腰鼓有两面,一面是红色的,一面是白色的.初二的苏大学神想给你这个oier出一道题.假设一共有N(1<=N<=20,000)个同学表演,表演刚开始每一个鼓都是红色面朝向观众,舞蹈老师会发出M(1<=M<=20,000)个指令,如果指令发给第i个

P2253 好一个一中腰鼓!

P2253 好一个一中腰鼓! 本蒟蒻第一次用线段树做连续最长子段 线段树是将一个大区间二分成两个小区间,通过递归解决两个小区间的问题,然后合并.得到大区间的解. 类比一下分治法求单个最长连续子段. 每次也都是将一个大区间分成两个小区间.分别解决完小区间后.将小区间合并,从分界点左右遍历.暴力的求连续子序列的长度. 然后将两个小区间分别作为一个区间求解的最优值和从分界点的连续子段长度比较,然后就得到了这个大区间的最长连续子段的长度. 可是,如果在线段树中呢?每次从分界点暴力的求时间复杂度太高. 那

线段树 P2253 好一个一中腰鼓!

传送门 不得不说 这真是一道不错的线段树的题目 这一道题的大意就是说 一开始所有的状态均为0 会有m次指令 每一次可以把一个点的状态进行更改 原来是0就变成1 原来是1就变成0 为了锻炼代码能力 我决定还是中规中矩地写线段树 这一道题还规定了一种串  就是0和1间隔交替 (比如010101  101 01010) 你每一次更改之后 要求出所有的点组成的序列中最长的连续“01”串 那么这一道题如果用线段树来做 转移会稍微复杂一点 我们定义sum为当前区间最长的01串 lsum为当前区间最长的前缀0

【P2253】 好一个一中腰鼓!

Description 给定一个01子串和操作数,每次操作可以使一个元素0变为1, 1变为0,求区间最长连续相邻不相等的长度 Solution 对于最长连续不相等,我们可以用几个量来维护,为: 1  lf 从左边开始的最长连续相邻不相等最大长度 2 rf 从右边开始的最长连续相邻不相等最大长度 3 mf 内部的最长连续相邻不相等最大长度 所以,最长的长度为max(tr[1].lf, tr[1].rf, tr[1].mf),对于每一个变量我们可以这样维护 tr[x].lf = max(tr[x <

升序堆和降序堆(优先队列) 洛谷1801

1 // 洛谷1801 2 // 一个升序堆,一个降序堆 3 // 降序堆维护序列的前i个最小值 4 // 插如元素的时候,如果x小于降序堆最大值,则替换,并将最大值插入升序堆:否则,直接插入升序堆 5 // 每次输出升序堆的最小值即可 6 7 8 #include <bits/stdc++.h> 9 using namespace std; 10 #define LL long long 11 typedef pair<int,int> pii; 12 const int inf

VIjos——V 1782 借教室 | | 洛谷——P1083 借教室

https://vijos.org/p/1782|| https://www.luogu.org/problem/show?pid=1083 描述 在大学期间,经常需要租借教室.大到院系举办活动,小到学习小组自习讨论,都需要向学校申请借教室.教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样. 面对海量租借教室的信息,我们自然希望编程解决这个问题.我们需要处理接下来n天的借教室信息,其中第i天学校有ri个教室可供租借.共有m份订单,每份订单用三个正整数描述,分别为dj,sj,tj,表示

[洛谷P2580]于是他错误的点名开始了

洛谷P2580的一个水题,用啥都能过,不过为了联系一下刚刚学会的字典树,还是认真做一下吧. #include <cstdio> #include <cstring> using namespace std; #define idx(x) x - 'a' int n, m, nex; struct node { int next[26]; int val; }tree[1000001]; void Insert(char *s) { int i, rt = 0, len = strl

洛谷 P1193 洛谷团队训练VS传统团队训练

P1193 洛谷团队训练VS传统团队训练 题目背景 “在中学的信息学教育领域,洛谷无疑是一个相当受欢迎的辅助网站.同时有百余所学校正在通过洛谷进行信息学竞赛(以后简称OI)的教育.洛谷之所以如此受欢迎,是因为洛谷创新的将OI教育的几乎每一个环节都搬到了线上,无论是学校的竞赛教练还是学生,均可以仅仅使用这一个网站来进行练习,提升自己的能力.” ——摘自<厦门中小学教育科学研究>,2015年2月号. 题目描述 XX中学的两位信息组的教练正在为学校信息组是否应当将洛谷作为主要的训练工具而争论不休,最