zoukankan      html  css  js  c++  java
  • 【线段树】Petrozavodsk Summer Training Camp 2016 Day 6: Warsaw U Contest, XVI Open Cup Onsite, Sunday, August 28, 2016 Problem H. Hay

    有一些草,一开始高度都是0,它们的生长速率不同。

    给你一些单增的日期,在这些日期要将>b的草的部分都割掉,问你每次割掉的部分有多少。

    将草的生长速率从大到小排序,这样每次割掉的是一个后缀,而且不会影响它们生长速率的递增性。

    就是三种操作,一种对一个后缀赋值,一种对整个数组作 + 另一个数组(d(i)-d(i-1))*a,一种求区间和。

    可以通过打标记的线段树实现,标记下放通过预处理生长速率数组的前缀和可以实现。

    队友的代码:

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <map>
    #include <cstring>
    #include <vector>
    #include <ctime>
    using namespace std;
    
    struct nod{
    int l,r,ls,rs;
    long long sum,ma,lazyd,lazyge;
    }t[2000010];
    int num[500010],n,m,i,p,now;
    long long ans,pre,sum[500010],d,b;
    char c;
    void ge(int d,long long a)
    {
        t[d].lazyd=0;
        t[d].lazyge=a;
        t[d].sum=(t[d].r-t[d].l+1)*a;
        t[d].ma=a;
    }
    
    void addday(int d,long long a)
    {
        t[d].lazyd+=a;
        t[d].sum+=(sum[t[d].r]-sum[t[d].l-1])*a;
        t[d].ma+=num[t[d].r]*a;
    }
    
    void lazy(int d)
    {
        int ls=t[d].ls,rs=t[d].rs;
        if (t[d].lazyge!=-1)
        {
            ge(ls,t[d].lazyge);
            ge(rs,t[d].lazyge);
            t[d].lazyge=-1;
        }
        if (t[d].lazyd!=0)
        {
            addday(ls,t[d].lazyd);
            addday(rs,t[d].lazyd);
            t[d].lazyd=0;
        }
    
    }
    
    int buildtree(int l,int r)
    {
        int k,mid;
        k=++p;
        t[k].l=l;
        t[k].r=r;
        t[k].lazyge=-1;
        if (l==r) return k;
        mid=(l+r)/2;
        t[k].ls=buildtree(l,mid);
        t[k].rs=buildtree(mid+1,r);
        return k;
    }
    
    int find(int d,long long a)
    {
        if (t[d].l==t[d].r) return t[d].l;
        lazy(d);
        if (t[t[d].ls].ma>a) return find(t[d].ls,a);
        return find(t[d].rs,a);
    }
    
    long long getsum(int d,int l,int r)
    {
        int mid;
        if (l<=t[d].l && r>=t[d].r) return t[d].sum;
        mid=(t[d].l+t[d].r)/2;
        lazy(d);
        if (r<=mid) return getsum(t[d].ls,l,r);
        if (l>mid) return getsum(t[d].rs,l,r);
        return getsum(t[d].ls,l,mid)+getsum(t[d].rs,mid+1,r);
    }
    
    void modify(int d,int l,int r,long long a)
    {
        int mid;
        if (l<=t[d].l && r>=t[d].r)
        {
            ge(d,a);
            return;
        }
        lazy(d);
        mid=(t[d].l+t[d].r)/2;
        if (l>mid) modify(t[d].rs,l,r,a);
        if (r<=mid) modify(t[d].ls,l,r,a);
        if (l<=mid && r>mid)
        {
            modify(t[d].ls,l,mid,a);
            modify(t[d].rs,mid+1,r,a);
        }
        t[d].ma=max(t[t[d].ls].ma,t[t[d].rs].ma);
        t[d].sum=(t[t[d].ls].sum+t[t[d].rs].sum);
    }
    
    long long read()
    {
        c=getchar(); ans=0;
        while (c<'0' || c>'9') c=getchar();
        while (c>='0' && c<='9')
        {
            ans=ans*10+c-48;
            c=getchar();
        }
        return ans;
    }
    
    int main()
    {
        //freopen("ac.in","r",stdin);
        //freopen("ac.out","w",stdout);
        scanf("%d%d",&n,&m);
        buildtree(1,n);
        for (i=1;i<=n;i++) num[i]=read();
        sort(num+1,num+n+1);
        for (i=1;i<=n;i++) sum[i]=sum[i-1]+num[i];
        for (i=1;i<=m;i++)
        {
            d=read(); b=read();
            addday(1,d-pre);
            if (t[1].ma<=b)
            {
                pre=d;
                printf("0
    ");
                continue;
            }
            now=find(1,b);
            printf("%lld
    ",getsum(1,now,n)-b*(n-now+1));
            modify(1,now,n,b);
            pre=d;
        }
    }
  • 相关阅读:
    『嗨威说』算法设计与分析
    『嗨威说』算法设计与分析
    『嗨威说』算法设计与分析
    『嗨威说』算法设计与分析
    『嗨威说』数据结构
    『嗨威说』数据结构
    『嗨威说』数据结构
    『嗨威说』数据结构
    『嗨威说』数据结构
    『嗨威说』数据结构的基本概念和术语、算法分析的时间复杂度(深度剖析)
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/7327404.html
Copyright © 2011-2022 走看看