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

hdu 1540(线段树区间合并)

时间:2018-12-31 13:08:05      阅读:213      评论:0      收藏:0      [点我收藏+]

标签:update   detail   blank   oid   长度   pos   scan   ||   std   

题目链接:传送门

参考文章:传送门

题意:n个数字初始连在一条线上,有三种操作,

D x表示x号被摧毁;

R 表示恢复剩下的通路

Q表示查询标号为x所在的串的最长长度。

思路:线段树的区间合并。

技术分享图片
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 50500;
struct Node{
    int l,r;
    int ls,rs,ms;
}cur[maxn<<2]; 
int ss[maxn],m,n;
void build(int x,int l,int r) //初始化建树 
{
    cur[x].l=l;cur[x].r=r;
    cur[x].ls=cur[x].rs=cur[x].ms=r-l+1;
    if(l==r) return ;
    int mid=(l+r)>>1;
    build(x*2,l,mid);
    build(x*2+1,mid+1,r);
}
int MAX(int x,int y)
{
    return x>y?x:y;
}
void update(int x,int pos,int fg)
{
    if(cur[x].l==cur[x].r)
    {
        if(fg==0) cur[x].ls=cur[x].rs=cur[x].ms=0; //删除 
        else cur[x].ls=cur[x].rs=cur[x].ms=1; //更新 
        return ;
    }
    int mid=(cur[x].l+cur[x].r)>>1;
    if(pos<=mid) update(x*2,pos,fg);
    else update(x*2+1,pos,fg);
    //pushup操作,更新左子区间,右子区间的最长长度 
    cur[x].ls=cur[x*2].ls;
    cur[x].rs=cur[x*2+1].rs;
    cur[x].ms=MAX(MAX(cur[x*2].ms,cur[x*2+1].ms),cur[x*2].rs+cur[x*2+1].ls);  
    if(cur[x*2].ls==cur[x*2].r-cur[x*2].l+1) cur[x].ls+=cur[x*2+1].ls; //如果区间的左子树的左区间已经满了,就加上右子树的左子区间 
    if(cur[x*2+1].rs==cur[x*2+1].r-cur[x*2+1].l+1) cur[x].rs+=cur[x*2].rs; // 如果右子树的右子区间已经满了,就加上左子树的右子区间 
}
int query(int x,int pos)
{
    if(cur[x].ms==0||cur[x].l==cur[x].r||cur[x].ms==cur[x].r-cur[x].l+1) return cur[x].ms;
    int mid=(cur[x].l+cur[x].r)>>1;
    if(pos<=mid)
    {
        if(pos>=cur[x*2].r-cur[x*2].rs+1) return query(x*2,pos)+query(x*2+1,mid+1);//如果在左子区间的右边界,就遍历两个区间 
        return query(x*2,pos); 
    } 
    else
    {
        if(pos<=cur[x*2+1].l+cur[x*2+1].ls-1) return query(x*2+1,pos)+query(x*2,mid); //如果在右子区间的左边界,就遍历两个区间 
        return query(x*2+1,pos);
    }
}
int main(void)
{
    while(~scanf("%d%d",&n,&m))
    {
        build(1,1,n);
        char op[2];
        int x,top=0;
        while(m--)
        {
            scanf("%s",op);
            if(op[0]==D)
            {
                scanf("%d",&x);
                ss[top++]=x;
                update(1,x,0);
            }
            else if(op[0]==Q)
            {
                scanf("%d",&x);
                printf("%d\n",query(1,x));
            }
            else if(op[0]==R)
            {
                x=ss[--top];
                update(1,x,1);
            }
        }
    }
    return 0;
}
View Code

 

hdu 1540(线段树区间合并)

标签:update   detail   blank   oid   长度   pos   scan   ||   std   

原文地址:https://www.cnblogs.com/2018zxy/p/10201702.html

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