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;
    }
  • 相关阅读:
    四、MYSQL的数据类型
    一、InnoDB引擎
    Spring源码分析(一)
    ActiveMQ 的安装与使用(springboot版本)
    12、JAVA内存模型与线程
    9、虚拟机字节码执行引擎
    8、类加载机制
    7、Class文件的格式
    6、使用jconsole+VisualVM分析JVM
    5、JVM的监控与分析工具
  • 原文地址:https://www.cnblogs.com/Invictus-Ocean/p/13340975.html
Copyright © 2011-2022 走看看