zoukankan      html  css  js  c++  java
  • 【BZOJ2527】Meteors(POI2011)-整体二分+树状数组

    测试地址:Meteors
    题目大意:一个环上有m个区域,有n个国家,每个国家管辖一些区域,有k场陨石雨陆续降落,每场陨石雨会给一个环上的区间内的每个区域提供Ai颗陨石,现在每个国家都有采样任务,即要在他们管辖的区域中收集共Pi颗陨石,问每个国家最早在第几场陨石雨后就可以完成任务。
    做法:本题需要用到整体二分+树状数组。
    首先,如果只有一个询问,我们就可以用二分答案+树状数组统计来算出答案(区间加,单点修改可以差分后用树状数组维护),时间复杂度为O(nlog2n)。而这题有多个询问,又没有强制在线,因此考虑整体二分。
    我们需要完成函数solve(s,t,l,r),表示要处理的询问区间为[s,t],它们的答案已知在区间[l,r]中。那么按照套路,我们令区间[l,r]的中点为mid,考虑在区间[l,mid]的所有操作对询问的影响,这一步可以用树状数组完成,然后将所有询问进一步分治求解。我们来分析该算法的时间复杂度,显然所有操作的总时间复杂度是O(nlog2n)的,而对于一个询问,它会被计算logn次,那么所有询问的总时间复杂度就是O(nlog2n)的,因此算法的总时间复杂度就是O(nlog2n),可以通过此题。
    以下是本人代码:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    int n,m,k,first[300010]={0},nxt[300010],ans[300010];
    int L[300010],R[300010];
    ll sum[300010]={0},A[300010];
    struct query
    {
        int id;
        ll limit,sum;
    }q[300010],q1[300010],q2[300010];
    
    int lowbit(int x)
    {
        return x&(-x);
    }
    
    void add(int l,int r,ll c)
    {
        for(int i=l;i<=m;i+=lowbit(i))
            sum[i]+=c;
        for(int i=r+1;i<=m;i+=lowbit(i))
            sum[i]-=c;
    }
    
    ll query(int x)
    {
        ll ans=0;
        for(int i=x;i;i-=lowbit(i))
            ans+=sum[i];
        return ans;
    }
    
    void solve(int s,int t,int l,int r)
    {
        if (s>t) return;
        if (l==r)
        {
            for(int i=s;i<=t;i++)
                ans[q[i].id]=l;
            return;
        }
    
        int mid=(l+r)>>1,tot1=0,tot2=0;
        for(int i=l;i<=mid;i++)
        {
            if (L[i]<=R[i]) add(L[i],R[i],A[i]);
            else add(1,R[i],A[i]),add(L[i],m,A[i]);
        }
    
        for(int i=s;i<=t;i++)
        {
            ll s=0;
            int now=first[q[i].id];
            while(now)
            {
                s+=query(now);
                if (q[i].sum+s>=q[i].limit) break;
                now=nxt[now];
            }
            if (q[i].sum+s>=q[i].limit) q1[++tot1]=q[i];
            else q[i].sum+=s,q2[++tot2]=q[i];
        }
        for(int i=1;i<=tot1;i++)
            q[s+i-1]=q1[i];
        for(int i=1;i<=tot2;i++)
            q[s+tot1+i-1]=q2[i];
    
        for(int i=l;i<=mid;i++)
        {
            if (L[i]<=R[i]) add(L[i],R[i],-A[i]);
            else add(1,R[i],-A[i]),add(L[i],m,-A[i]);
        }
    
        solve(s,s+tot1-1,l,mid);
        solve(s+tot1,t,mid+1,r);
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            int x;
            scanf("%d",&x);
            nxt[i]=first[x];
            first[x]=i;
        }
    
        for(int i=1;i<=n;i++)
            scanf("%lld",&q[i].limit);
        scanf("%d",&k);
        for(int i=1;i<=k;i++)
            scanf("%d%d%lld",&L[i],&R[i],&A[i]);
        for(int i=1;i<=n;i++)
            q[i].id=i,q[i].sum=0;
        solve(1,n,1,k+1);
        for(int i=1;i<=n;i++)
        {
            if (ans[i]==k+1) printf("NIE
    ");
            else printf("%d
    ",ans[i]);
        }
    
        return 0;
    }
  • 相关阅读:
    腾讯精品课程
    什么都没有,先空出来!
    Python3-super().__init()__
    Python3-模块
    Python3-单例模式
    Python3-私有化修改
    Python3-私有属性
    Python3-面向对象-魔术方法
    Python3-面向对象-四种方法
    Python3-迭代器
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793366.html
Copyright © 2011-2022 走看看