zoukankan      html  css  js  c++  java
  • poj-3667(线段树区间合并)

    题目链接:传送门

    参考文章:传送门

    思路:线段树区间合并问题,每次查询到满足线段树的区间最左值,然后更新线段树。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int maxn = 50500;
    int lsum[maxn<<2],rsum[maxn<<2],msum[maxn<<2],cover[maxn<<2];
    void build(int x,int l,int r)
    {
        lsum[x]=rsum[x]=msum[x]=r-l+1;
        if(l==r) return ;
        int mid=(l+r)>>1;
        build(x<<1,l,mid);
        build(x<<1|1,mid+1,r);
    }
    int MAX(int x,int y)
    {
        return x>y?x:y;
    }
    void pushup(int x,int k)
    {
        lsum[x]=lsum[x<<1];
        rsum[x]=rsum[x<<1|1];
        msum[x]=MAX(MAX(msum[x<<1],msum[x<<1|1]),lsum[x<<1|1]+rsum[x<<1]);
        if(lsum[x<<1]==(k-(k>>1))) lsum[x]+=lsum[x<<1|1];
        if(rsum[x<<1|1]==k>>1) rsum[x]+=rsum[x<<1];
    }
    void pushdown(int x,int k)
    {
        if(cover[x]!=-1)
        {
            cover[x<<1]=cover[x<<1|1]=cover[x];
            lsum[x<<1]=rsum[x<<1]=msum[x<<1]=cover[x]?0:(k-(k>>1));
            lsum[x<<1|1]=rsum[x<<1|1]=msum[x<<1|1]=cover[x]?0:(k>>1);
            cover[x]=-1;
        }
    }
    void update(int x,int l,int r,int A,int B,int Item)
    {
        if(A<=l&&r<=B) 
        {
            cover[x]=Item;
            lsum[x]=rsum[x]=msum[x]=Item?0:r-l+1;
            return ;
        }
        pushdown(x,r-l+1);
        int mid=(l+r)>>1;
        if(A<=mid) update(x<<1,l,mid,A,B,Item);
        if(B>mid) update(x<<1|1,mid+1,r,A,B,Item);
        pushup(x,r-l+1);
    }
    int query(int x,int l,int r,int len)
    {
        if(l==r) return 1;
        pushdown(x,r-l+1);
        int mid=(l+r)>>1;
        if(msum[x<<1]>=len) return query(x<<1,l,mid,len);
        else if(rsum[x<<1]+lsum[x<<1|1]>=len) return mid-rsum[x<<1]+1;
        else return query(x<<1|1,mid+1,r,len);
    }
    int main(void)
    {
        int n,m,i,x,y,z;
        while(~scanf("%d%d",&n,&m))
        {
            build(1,1,n);
            while(m--)
            {
                scanf("%d",&x);
                if(x==1)
                {
                    scanf("%d",&y);
                    if(msum[1]<y)
                    {
                        printf("0
    ");
                        continue;
                    }
                    z=query(1,1,n,y);
                    printf("%d
    ",z);
                    update(1,1,n,z,z+y-1,1);
                }
                else
                {
                    scanf("%d%d",&y,&z);
                    update(1,1,n,y,y+z-1,0);
                }
            }
        }
        return 0;
    }
    View Code

    http://poj.org/problem?id=3667

  • 相关阅读:
    uva 11404 Palindromic Subsequence(LCS回文串,最小字典序)
    paip.输入法编程---输入法ATIaN历史记录 v8b
    uva 10859 Placing Lampposts (树形dp)
    【设计模式】学习笔记8:命令模式
    Android自定义ProgressDialog
    (二十四)解释器模式详解
    Hadoop--两个简单的MapReduce程序
    BMP图像的灰度化---C++实现
    android 数组数据绑定到listview
    Win64 驱动内核编程-10.突破WIN7的PatchGuard
  • 原文地址:https://www.cnblogs.com/2018zxy/p/10204329.html
Copyright © 2011-2022 走看看