ACdream 1101 瑶瑶想要玩滑梯

没想到线段树的基本用法这么长时间没写了还没有忘,1A的感觉还是很爽的。

题目大意:

中文题,点此查看题目。


解题思路:

线段树的区间更新与查询。

lazy标记的使用。

当需要返回区间多个值时可以使用引用参数。



下面是代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <math.h>
#include <stdlib.h>

using namespace std;

int min(int a,int b)
{
    if(a>b)a=b;
    return a;
}
int max(int a,int b)
{
    if(a<b)a=b;
    return a;
}
int n,m,l,r,x;
struct node1
{
    int num,l,r,lcnt,rcnt,mcnt;
} node[100000<<2];
char s[3];
void PushUp(int l,int r,int m,int tr)
{
    node[tr].num=-1;
    node[tr].l=node[tr<<1].l;
    node[tr].r=node[tr<<1|1].r;
    node[tr].lcnt=node[tr<<1].lcnt;
    if(node[tr<<1].lcnt==m-l+1&&node[tr<<1].r<node[tr<<1|1].l)
    {
        node[tr].lcnt+=node[tr<<1|1].lcnt;
    }
    node[tr].rcnt=node[tr<<1|1].rcnt;
    if(node[tr<<1|1].rcnt==r-m&&node[tr<<1].r<node[tr<<1|1].l)
    {
        node[tr].rcnt+=node[tr<<1].rcnt;
    }
    if(node[tr<<1].r<node[tr<<1|1].l)
    {
        node[tr].mcnt=node[tr<<1].rcnt+node[tr<<1|1].lcnt;
    }
    else node[tr].mcnt=0;
    node[tr].mcnt=max(node[tr<<1].mcnt,max(node[tr<<1|1].mcnt,max(node[tr].lcnt,max(node[tr].rcnt,node[tr].mcnt))));
}
void build(int l,int r,int tr)
{
    if(l==r)
    {
        scanf("%d",&node[tr].num);
        node[tr].l=node[tr].num;
        node[tr].r=node[tr].num;
        node[tr].lcnt=1;
        node[tr].rcnt=1;
        node[tr].mcnt=1;
        return ;
    }
    int m=(l+r)>>1;
    build(l,m,tr<<1);
    build(m+1,r,tr<<1|1);
    PushUp(l,r,m,tr);
}
void Pushdown(int l,int r,int tr)
{
    if(node[tr].num!=-1)
    {
        node[tr<<1]=node[tr];
        node[tr<<1|1]=node[tr];
        node[tr].num=-1;
    }
}
void Update(int L,int R,int num,int l,int r,int tr)
{
    if(L<=l&&r<=R)
    {
        if(node[tr].num==-1)node[tr].num=0;
        node[tr].num+=num;
        node[tr].l=num;
        node[tr].r=num;
        node[tr].lcnt=1;
        node[tr].rcnt=1;
        node[tr].mcnt=1;
        return ;
    }
    if(l==r)return;
    Pushdown(l,r,tr);
    int m=(l+r)>>1;
    if(m>=L)Update(L,R,num,l,m,tr<<1);
    if(m<R)Update(L,R,num,m+1,r,tr<<1|1);
    PushUp(l,r,m,tr);
}
void copy1(int a,int b,int c,int d,int e,int &a1,int &b1,int &c1,int &d1,int &e1)
{
    a1=a;
    b1=b;
    c1=c;
    d1=d;
    e1=e;
}
void query(int L,int R,int l,int r,int tr,int &lcnt,int &lnum,int &rcnt,int &rnum,int &mnum)
{
    if(L<=l&&r<=R)
    {
        mnum=node[tr].mcnt;
        lcnt=node[tr].lcnt;
        lnum=node[tr].l;
        rcnt=node[tr].rcnt;
        rnum=node[tr].r;
        return;
    }
    if(l==r)return;
    int m=(l+r)>>1,a[2]={0},b[2]={0},c[2]={0},d[2]={0},e[2]={0};
    Pushdown(l,r,tr);
    if(m>=L)
    {
        query(L,R,l,m,tr<<1,a[0],b[0],c[0],d[0],e[0]);
    }
    if(m<R)
    {
        query(L,R,m+1,r,tr<<1|1,a[1],b[1],c[1],d[1],e[1]);
    }
    if(c[0]!=0)
    {
        if(a[1]!=0)
        {
            mnum=max(e[0],e[1]);
            lcnt=a[0];
            lnum=b[0];
            rcnt=c[1];
            rnum=d[1];
            if(d[0]<b[1])
            {
                mnum=max(mnum,c[0]+a[1]);
                if(a[0]==e[0]&&a[0]==m-l+1)
                {
                    lcnt+=a[1];
                }
                if(c[1]==e[1]&&c[1]==r-m)
                {
                    rcnt+=c[0];
                }
            }
        }
        else
        {
            copy1(a[0],b[0],c[0],d[0],e[0],lcnt,lnum,rcnt,rnum,mnum);
        }
    }
    else
    {
        copy1(a[1],b[1],c[1],d[1],e[1],lcnt,lnum,rcnt,rnum,mnum);
    }
    PushUp(l,r,m,tr);
    return ;
}
int main()
{
    scanf("%d%d",&n,&m);
    build(1,n,1);
    int temp[5];
    for(int i=0; i<m; i++)
    {
        scanf("%s",s);
        if(s[0]=='Q')
        {
            scanf("%d%d",&l,&r);
            query(l,r,1,n,1,temp[0],temp[1],temp[2],temp[3],temp[4]);
            printf("%d\n",max(temp[0],max(temp[2],temp[4])));
        }
        else if(s[0]=='U')
        {
            scanf("%d%d%d",&l,&r,&x);
            Update(l,r,x,1,n,1);
        }
    }
    return 0;
}


你可能感兴趣的:(线段树,刷题,ACdream)