zoukankan      html  css  js  c++  java
  • BZOJ4293 Siano

    题头:

    描述
    农夫Byteasar买了一片n亩的土地,他要在这上面种草。 他在每一亩土地上都种植了一种独一无二的草,其中,第i亩土地的草每天会长高a[i]厘米。 Byteasar一共会进行m次收割,其中第i次收割在第d[i]天,并把所有高度大于等于b[i]的部分全部割去。Byteasar想知道,每次收割得到的草的高度总和是多少,你能帮帮他吗?
    Input
    第一行包含两个正整数n,m(1<=n,m<=500000),分别表示亩数和收割次数。 第二行包含n个正整数,其中第i个数为ai,依次表示每亩种植的草的生长能力。 接下来m行,每行包含两个正整数d[i],bi,依次描述每次收割。 数据保证d[1] < d[2] <… < d[m],并且任何时刻没有任何一亩草的高度超过10^12。
    Output
    输出m行,每行一个整数,依次回答每次收割能得到的草的高度总和。
    样例输入
    4 4
    1 2 4 3
    1 1
    2 2
    3 0
    4 4
    样例输出
    6
    6
    18
    0

    仔细读题
    我们需要两个标记
    一个mark进行区间加的操作(mark维护天数,实际增加的值是mark[ i ]*a[ i ])
    还需要一个marks进行区间更改为的操作
    然后对于每次输入
    mark增加的值为这一次输入的时间减上一次输入的时间
    然后我们维护两个值:区间和和区间最大值(两次区间和相减即使所求答案,区间最大值是方便进行区间更改为的操作,因为这样我们只需要下传标记到区间最大值大于b[ i ]的区间)
    维护区间和需要把区间a的值的和乘上mark,区间最大值加上天数乘区间a的最大值;
    我们只需要先从小到大排个序,保证单调性,这样找到最后一个高度小于b[ i ]的位置,我们就可以直接把从这儿往后都打上标记

    代码如下

    //siano
    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    inline ll read(){
    	char ch;
    	while((ch=getchar())<'0'||ch>'9'){;}
    	ll res=ch-'0';
    	while((ch=getchar())>='0'&&ch<='9')
    	res=res*10+ch-'0';
    	return res;
    } 
    long long a[500005],tre[2000007],mark[2000007],maxn[2000007],sum[500005],marks[2000007],d1;
    //tre:记录区间和,sum
    int n,m,l[2000007],r[2000007];
    inline ll max(ll a,ll b)
    {
    	return a>b?a:b;
    }
    inline void buildtree(int p,int st,int end){
        l[p]=st,r[p]=end,mark[p]=0,marks[p]=-1;
    //marks初始化为-1,不能初始化为0(有可能是更改为0)
        if(st==end){tre[p]=maxn[p]=0;return;}
        int mid=(st+end)>>1;
        buildtree(p<<1,st,mid),buildtree((p<<1)+1,mid+1,end);
    }
    inline void pushup(int root)
    //向上传递
    {
    	maxn[root]=max(maxn[(root<<1)],maxn[(root<<1)+1]);
    	tre[root]=tre[(root<<1)]+tre[(root<<1)+1];
    }
    inline void pushnow(int root,ll v){
    //用mark更改区间
    	mark[root]+=v;
    	tre[root]+=v*(sum[r[root]]-sum[l[root]-1]);
    	maxn[root]+=v*a[r[root]];
    }
    inline void pushnown(int root,ll k)
    //用marks更改区间
    {
    	marks[root]=k;
    	maxn[root]=k;
    	tre[root]=k*(r[root]-l[root]+1);
    	mark[root]=0;
    //因为更改区间以后前面的操作打下的mark,对当前答案不会有影响,所以把mark变为0;
    }
    inline void pushDown(int root)
    //向下传递
    {
    	if(marks[root]!=-1)
    	{
    		pushnown((root<<1),marks[root]);
    		pushnown((root<<1)+1,marks[root]);
    		marks[root]=-1;
    	}
        if(mark[root])
        {
            pushnow((root<<1),mark[root]);
            pushnow((root<<1)+1,mark[root]);
            mark[root]=0;
        }
    }
    inline void modify(int root,int ql,int qr,ll v){
    //更改区间值
        if(ql>r[root]||qr<l[root])return;
        if(ql<=l[root]&&r[root]<=qr){pushnown(root,v);return;}
        pushDown(root);
        int mid=(l[root]+r[root])>>1;
        if(qr<=mid)modify((root<<1),ql,qr,v);
        else if(ql>mid)modify((root<<1)+1,ql,qr,v);
        else modify((root<<1),ql,mid,v),modify((root<<1)+1,mid+1,qr,v);
        pushup(root);
    }
    inline ll query(int root,ll v){
    //查找第一个小于等于b[ i ]的位置    
    	if(l[root]==r[root])return l[root];
        pushDown(root);
        if(maxn[(root<<1)]<=v)return query((root<<1)+1,v);
        return query((root<<1),v);
    }
    
    int  main(){
    	n=read(),m=read();
    	for(int  i=1;i<=n;i++)
    	{
    		a[i]=read();
    	}
    	sort(a+1,a+1+n);
    	buildtree(1,1,n);
    	for(int i=1;i<=n;i++)
    	sum[i]=sum[i-1]+a[i];
    	d1=0;
    	for(int i=1;i<=m;i++)
    	{
    		ll d2=read(),b=read();
    		maxn[1]+=(d2-d1)*a[n],tre[1]+=(d2-d1)*sum[n],mark[1]+=(d2-d1);
    		if(maxn[1]<=b)
    		{
    			puts("0"),d1=d2;
    			continue;
    		}
    		ll res=tre[1];
    		int  pos=query(1,b);
            modify(1,pos,n,b);
            cout<<res-tre[1]<<'
    ',d1=d2;
    	}
    	return 0;
    }
    
  • 相关阅读:
    C语言II博客作业01
    vscode使用相关配置
    Ubuntu配置教程
    编译原理复习
    误差与过拟合
    机器学习分类
    SQL语句使用详解
    CRC模2除法
    数据链路层之差错控制(检错编码和纠错编码)->(奇偶校验码、CRC循环冗余码、海明码)
    封装成帧、帧定界、帧同步、透明传输(字符计数法、字符串的首尾填充法、零比特填充的首尾标志法、违规编码法)
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/10366527.html
Copyright © 2011-2022 走看看