zoukankan      html  css  js  c++  java
  • hdu 1540(线段树区间合并)

    题目链接:传送门

    参考文章:传送门

    题意: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
    ",query(1,x));
                }
                else if(op[0]=='R')
                {
                    x=ss[--top];
                    update(1,x,1);
                }
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Oracle数据库限定特定用户 特定IP 登录
    Elasticsearch 监控
    Elasticsearch 使用:创建、插入、查询、更新、删除
    ES 的基本用法
    elasticsearch 集群管理(集群规划、集群搭建、集群管理)
    ElasticSearch 集群环境搭建,安装ElasticSearch-head插件,安装错误解决
    Greenplum 基准测试
    MySQL 计算时间差函数 TIMESTAMPDIFF、DATEDIFF
    PostgreSQL 时间函数 extract函数
    Greenplum最佳实践
  • 原文地址:https://www.cnblogs.com/2018zxy/p/10201702.html
Copyright © 2011-2022 走看看