ACdream 1101 瑶瑶想要玩滑梯

瑶瑶想要玩滑梯

Time Limit: 2000/1000MS (Java/Others) Memory Limit: 512000/256000KB (Java/Others)
Problem Description

众所周知,瑶瑶(tsyao)是个贪玩的萌妹子,特别喜欢闹腾,恰好今天是一个风和日丽的日子,瑶瑶嚷着让姐姐带她去去公园玩滑梯,可是公园的滑梯比较独特,由单位积木搭成,积木是排成一排搭好,每列有xi个积木,共n列。小明能够对积木进行m次操作:

1.U L R yi         : 将[L,R]列的积木高度全都改为yi

2.Q L R           : 查询[L,R]列最长连续上升的列长度(LCIS)

知道[L,R]列最长连续上升的列长度过后,瑶瑶就可以开开心心地玩滑梯啦!

Ps:连续上升的列长度指对于一段合法区间,都有

       话说积木是平的,瑶瑶是怎么从高处滑到低处的呢??作为姐姐也不知道,很想知道吧?你去问她吧。。

Input

第一行 两个整数n,m;

第二行 n个整数,分别为[1,n]区间每列积木个数;

接下来m行为m个操作

Output

输出x行,每行为每次操作2的查询结果。

Sample Input
5 4
2 1 2 3 1
Q 1 4
Q 2 5
U 2 4 3
Q 1 5
Sample Output
3
3
2
Hint

对于 100%的数据,有1 ≤ n ≤ 10^5 , 1 ≤ m ≤ 10^5 , 1 ≤ xi ≤ 10^8。

单组输入,共10组数据。

Source
tsyao
Manager

tsyao



线段树区间更新,区间合并,维护每个区间的两个端点。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#include <iostream>
#include <cmath>
#include <queue>
#include <vector>
#include <set>
#include <cstdlib>
#include <time.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int Maxn=1e5+5;
const int N=Maxn*7+5;
int maxn[N],maxl[N],maxr[N];
int numl[N],numr[N],vis[N];
int a[Maxn];
void PushUp(int l,int r,int rt)
{
    int m=(l+r)>>1;
    maxn[rt]=max(maxn[rt<<1],maxn[rt<<1|1]);
    maxl[rt]=maxl[rt<<1];
    maxr[rt]=maxr[rt<<1|1];
    numl[rt]=numl[rt<<1];
    numr[rt]=numr[rt<<1|1];
    if(numr[rt<<1]<numl[rt<<1|1])
    {
        maxn[rt]=max(maxn[rt],maxr[rt<<1]+maxl[rt<<1|1]);
        if(maxl[rt]==m-l+1)
            maxl[rt]+=maxl[rt<<1|1];
        if(maxr[rt]==r-m)
            maxr[rt]+=maxr[rt<<1];
    }
}
void Pushdown(int rt)
{
    if(vis[rt])
    {
        vis[rt<<1]=vis[rt<<1|1]=vis[rt];
        numl[rt<<1]=numr[rt<<1]=vis[rt<<1];
        maxl[rt<<1]=maxr[rt<<1]=maxn[rt<<1]=1;
        numl[rt<<1|1]=numr[rt<<1|1]=vis[rt<<1|1];
        maxl[rt<<1|1]=maxr[rt<<1|1]=maxn[rt<<1|1]=1;
        vis[rt]=0;
    }
}
void build(int l,int r,int rt)
{
    vis[rt]=0;
    if(l==r)
    {
        maxn[rt]=maxl[rt]=maxr[rt]=1;
        numl[rt]=numr[rt]=a[l];
    }
    else
    {
        int m=(l+r)/2;
        build(lson);
        build(rson);
        PushUp(l,r,rt);
    }
}
void update(int L,int R,int c,int l,int r,int rt)
{
    if(L<=l &&r<=R)
    {
        maxn[rt]=maxl[rt]=maxr[rt]=1;
        numl[rt]=numr[rt]=vis[rt]=c;
        return;
    }
    Pushdown(rt);
    int m=(l+r)>>1;
    if(L<=m)update(L,R,c,lson);
    if(m<R)update(L,R,c,rson);
    PushUp(l,r,rt);
}
int query(int L,int R,int l,int r,int rt)
{
    if(L<=l &&r<=R)
        return maxn[rt];
    Pushdown(rt);
    int tmp1,tmp2,tmp3;
    tmp1=tmp2=tmp3=0;
    int m=(l+r)>>1;
    if(L<=m)tmp1=query(L,R,lson);
    if(m<R)tmp2=query(L,R,rson);
    if(L<=m &&m<R)
    {
        if(numr[rt<<1]<numl[rt<<1|1])
            tmp3=min(maxr[rt<<1],m-L+1)+min(maxl[rt<<1|1],R-m);
    }
    return max(tmp1,max(tmp2,tmp3));
}
int main()
{
    int n,m;
    char pp[2];
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(int i=1; i<=n; i++)
            scanf("%d",&a[i]);
        build(1,n,1);
        int x,y,z;
        for(int i=1; i<=m; i++)
        {
            scanf("%s",pp);
            if(pp[0]=='Q')
            {
                scanf("%d%d",&x,&y);
                printf("%d\n",query(x,y,1,n,1));
            }
            else
            {
                scanf("%d%d%d",&x,&y,&z);
                update(x,y,z,1,n,1);
            }
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值