zoukankan      html  css  js  c++  java
  • 【BZOJ4631】踩气球 题解(线段树)

    题目链接

    ----------------------

    题目大意:给定一个长度为$n$的序列${a_i}$。现在有$m$个区间$[l_i,r_i]$和$q$个操作,每次选取一个$x$使得$a_x--$。问每一次操作后区间和为$0$的区间个数。

    可以用主席树解决,但蒟蒻不会,蒟蒻只会写线段树QAQ。

    对于每一个区间$[l_i,r_i]$,我们可以把它分解成线段树上$s$个区间,线段树每个结点维护一个向量数组,用来存包含它的区间。当某一个$a_x--$后,看线段树上区间和是否为0,如果是那么包含这个区间的区间$s--$。如果$s=0$那么$ans++$。

    注意$update$向上回溯时也要判断一下是否为0,进行更新。

    时间复杂度$O((m+q)log n+n)$。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    int n,q,m,a[100005],ans;
    struct node
    {
        vector<int> v;
        int l,r,val;
    }tree[500005];
    struct Node
    {
        int l,r,s;
    }t[100005];
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    inline void build(int index,int l,int r)
    {
        tree[index].l=l;
        tree[index].r=r;
        if (l==r)
        {
            tree[index].val=a[l];
            return;
        }
        int mid=(l+r)>>1;
        build(index*2,l,mid);
        build(index*2+1,mid+1,r);
        tree[index].val=tree[index*2].val+tree[index*2+1].val;
    }
    inline void update(int index,int pos,int v)
    {
        if (tree[index].l==tree[index].r)
        {
            tree[index].val+=v;
            if (tree[index].val==0)
            {
                for (int i=0;i<tree[index].v.size();i++)
                {
                    t[tree[index].v[i]].s--;
                    if (t[tree[index].v[i]].s==0) ans++;
                }
            }
            return;
        }
        int mid=(tree[index].l+tree[index].r)>>1;
        if (pos<=mid) update(index*2,pos,v);
        else update(index*2+1,pos,v);
        tree[index].val=tree[index*2].val+tree[index*2+1].val;
        if (tree[index].val==0)
        {
            for (int i=0;i<tree[index].v.size();i++)
            {
                t[tree[index].v[i]].s--;
                if (t[tree[index].v[i]].s==0) ans++;
            }
        }
    }
    inline void split(int index,int l,int r,int id)
    {
        if (l<=tree[index].l&&tree[index].r<=r)
        {
            tree[index].v.push_back(id);
            t[id].s++;
            return;
        }
        int mid=(tree[index].l+tree[index].r)>>1;
        if (l<=mid) split(index*2,l,r,id);
        if (r>mid) split(index*2+1,l,r,id);
    }
    int main()
    {
        n=read(),m=read();
        for (int i=1;i<=n;i++) a[i]=read();
        build(1,1,n);
        for (int i=1;i<=m;i++) t[i].l=read(),t[i].r=read();
        for (int i=1;i<=m;i++) split(1,t[i].l,t[i].r,i);
        q=read();
        while(q--)
        {
            int x=read();
            x=(x+ans-1)%n+1;
            update(1,x,-1);
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    eclipse取消validation验证
    VMware12 pro装unlocker207补丁后依然没有apple mac选项,问题解决
    OSG学习:使用OSG中预定义的几何体
    技嘉主板+AMD CPU开启CPU虚拟化方法
    OSG学习:用多通道(multiple passes)实现透明度
    shader language学习(1)——shader language简介背景
    OSG学习:阴影代码示例
    代码整洁之道_条件判断
    springboot使用hibernate validator校验
    解决spring boot在RabbitMQ堆积消息情况下无法启动问题
  • 原文地址:https://www.cnblogs.com/Invictus-Ocean/p/13340975.html
Copyright © 2011-2022 走看看