惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
Simon Willison's Weblog
Simon Willison's Weblog
Microsoft Security Blog
Microsoft Security Blog
Y
Y Combinator Blog
The GitHub Blog
The GitHub Blog
Engineering at Meta
Engineering at Meta
F
Fortinet All Blogs
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
A
About on SuperTechFans
Last Week in AI
Last Week in AI
月光博客
月光博客
有赞技术团队
有赞技术团队
P
Proofpoint News Feed
MyScale Blog
MyScale Blog
Martin Fowler
Martin Fowler
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
C
Check Point Blog
U
Unit 42
The Register - Security
The Register - Security
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Hugging Face - Blog
Hugging Face - Blog
阮一峰的网络日志
阮一峰的网络日志
V
Visual Studio Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
D
DataBreaches.Net
WordPress大学
WordPress大学
aimingoo的专栏
aimingoo的专栏
H
Hacker News: Front Page
Recent Announcements
Recent Announcements
C
CXSECURITY Database RSS Feed - CXSecurity.com
Latest news
Latest news
小众软件
小众软件
P
Palo Alto Networks Blog
PCI Perspectives
PCI Perspectives
Security Latest
Security Latest
S
Secure Thoughts
Scott Helme
Scott Helme
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
Threat Research - Cisco Blogs
P
Proofpoint News Feed
M
MIT News - Artificial intelligence
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Google DeepMind News
Google DeepMind News
Recorded Future
Recorded Future
O
OpenAI News
S
Securelist
云风的 BLOG
云风的 BLOG
H
Help Net Security
T
Troy Hunt's Blog

博客园 - 糖豆爸爸

【树上DP前导知识汇总】 快速幂、龟速乘总结 反向建图+拓扑排序 卡特兰数专题(Catalan) AcWing 126. 最大的和 AcWing 431. 守望者的逃离 AcWing 414. 数字游戏 AcWing 468. 魔法阵 AcWing 463. 求和 洛谷 P1632 点的移动 P1056 NOIP2008 普及组 排座椅 洛谷 P1889 士兵站队 洛谷 P1862 输油管道问题 CF444C DZY Loves Colors SCOI2010 P2572 序列操作 P4344 SHOI2015 脑洞治疗仪 T125847 【模板】动态开点线段树 P3373 【模板】线段树 2 Physical Education Lessons
P2253 好一个一中腰鼓!
糖豆爸爸 · 2023-09-05 · via 博客园 - 糖豆爸爸

\(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 <bits/stdc++.h>
using namespace std;
const int N = 20010;

// 线段树
#define mid ((l + r) >> 1)
#define ls (u << 1)
#define rs (u << 1 | 1)
struct Node {
    int l, r, len;
    int lx, rx, mx; // lx:左起最长符合条件的长度;rx:右起最长符合条件的长度;mx:整体区间内符合条件的长度
} tr[N << 2];

int color[N]; // 每个位置上的颜色

void pushup(int u) {
    // 左儿子的最右端点颜色,与右儿子的最左端点颜色是否相同
    bool flag = color[tr[ls].r] != color[tr[rs].l];

    tr[u].lx = tr[ls].lx; // 左起最长,继承左儿子的左起最长
    // 如果左儿子全部区间满足条件,并且,左儿子最右,不等于,右儿子最左,也就是继续符合条件
    if ((tr[ls].lx == tr[ls].len) && flag) tr[u].lx = tr[ls].len + tr[rs].lx;

    tr[u].rx = tr[rs].rx; // 右起最长,继承右儿子的右起最长
    // 如果右儿子全部区间满足条件,并且,右儿子最左,不等于,左儿子最右,也就是继续符合条件
    if ((tr[rs].rx == tr[rs].len) && flag) tr[u].rx = tr[rs].len + tr[ls].rx;

    tr[u].mx = max(tr[ls].mx, tr[rs].mx);
    if (flag) tr[u].mx = max(tr[u].mx, tr[ls].rx + tr[rs].lx); // 拼接
}

void build(int u, int l, int r) {
    tr[u].l = l, tr[u].r = r, tr[u].len = r - l + 1;

    if (l == r) {
        tr[u].lx = tr[u].rx = tr[u].mx = 1; // 表演刚开始每一个鼓都是红色面朝向观众
        return;
    }
    build(ls, l, mid);
    build(rs, mid + 1, r);
    pushup(u);
}

void modify(int u, int p) {
    int l = tr[u].l, r = tr[u].r;
    if (l == r) {
        color[p] = !color[p]; // 红变白,白变红
        return;
    }
    if (p <= mid)
        modify(ls, p);
    else
        modify(rs, p);
    pushup(u);
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("P2253.in", "r", stdin);
#endif
    int n, m;
    cin >> n >> m;

    build(1, 1, n);

    while (m--) {
        int p;
        cin >> p;
        modify(1, p);
        printf("%d\n", tr[1].mx);
    }
    return 0;
}