码迷,mamicode.com
首页 > 其他好文 > 详细

洛谷 P2253 好一个一中腰鼓!

时间:2017-08-19 21:09:40      阅读:186      评论:0      收藏:0      [点我收藏+]

标签:提示   运动会   scanf   表示   targe   roo   odi   style   www   

题目背景

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

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>

struct Segment
{
    int l,r,mid,lm,rm,m,lcol,rcol;
    Segment * ch[2];
    Segment ()
    {
        ch[0]=ch[1]=NULL;
        lcol=rcol=lm=rm=m=0;
    }
};
int n,m;
int max(int a,int b) {return a>b?a:b;}
void pushup(Segment *&k)
{
    if(k->l==k->r) return;
    k->lcol=k->ch[0]->lcol;
    k->rcol=k->ch[1]->rcol;
    k->lm=k->ch[0]->lm;
    k->rm=k->ch[1]->rm;
    k->m=max(k->ch[0]->m,max(k->ch[1]->m,max(k->ch[0]->rm,k->ch[1]->lm)));
    if(k->ch[0]->rcol!=k->ch[1]->lcol)
    {
        k->m=max(k->m,k->ch[0]->rm+k->ch[1]->lm);
        if(k->ch[0]->lm==(k->ch[0]->r-k->ch[0]->l+1)) k->lm+=k->ch[1]->lm;
        if(k->ch[1]->rm==k->ch[1]->r-k->ch[1]->l+1) k->rm+=k->ch[0]->rm;
    }
}
void build(Segment *&k,int l,int r)
{
    k=new Segment;
    k->l=l;k->r=r;
    if(l==r) {k->lcol=k->rcol=0;k->lm=k->rm=k->m=1;return;}
    k->mid=l+r>>1;
    build(k->ch[0],l,k->mid);
    build(k->ch[1],k->mid+1,r);
    pushup(k);
}
void modify(Segment *&k,int t)
{
    if(k->l==k->r)
    {
        k->lcol=k->rcol^=1;
        return;
    }
    if(t<=k->mid) modify(k->ch[0],t);
    else modify(k->ch[1],t);
    pushup(k);
}
int Main()
{
    Segment * root=new Segment; 
    scanf("%d%d",&n,&m);
    build(root,1,n);
    for(int x;m--;)
    {
        scanf("%d",&x);
        modify(root,x);
        printf("%d\n",root->m);
    }
    return 0;
}
int sb=Main();
int main(int argc,char *argv[]) {;}

 

洛谷 P2253 好一个一中腰鼓!

标签:提示   运动会   scanf   表示   targe   roo   odi   style   www   

原文地址:http://www.cnblogs.com/ruojisun/p/7397785.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!