• bzoj4293: [PA2015]Siano


    这题搞了我一晚上……因为某些傻X的问题……

    窝这状态真是药丸TAT

    这个题嘛……大家的题解都说线段树,时限也开了30s明摆着告诉你是nlogn……

    不过我们发现a[i]<=10^6

    那么我就有一个以空间换时间的做法,并且只需要用很小的空间就可以把复杂度降到O(n)(或者说是O(maxa[i]+n))

    首先,这个被收割的稻草的A值显然有单调性,换句话说,每次收割都会有一个左端点

    接着,我们发现,如果初始高度确定,生长时间确定,收割的门槛也确定,那么被收割的最低高度是可以算出来的

    那么我们可以搞个单调栈,然后搞一搞就做完了

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #define ll long long
    #define N 1000006
    
    using namespace std;
    inline ll read(){
    	ll ret=0;char ch=getchar();
    	while (ch<'0'||ch>'9') ch=getchar();
    	while ('0'<=ch&&ch<='9'){
    		ret=ret*10-48+ch;
    		ch=getchar();
    	}
    	return ret;
    }
    int n;
    ll a[N],s[N];
    ll d[N/2],b[N/2],day;
    int stk[N/2],top;
    int to[N/2];
    const int m=1e6;
    
    int main(){
    	n=read();day=read();
    	for (int i=1;i<=n;++i) ++a[read()];
    	for (int i=1;i<=day;b[i++]=read()) d[i]=read();
    	s[0]=a[0]=0;
    	for (int i=1;i<=m;++i) s[i]=s[i-1]+(ll)a[i]*i;
    	for (int i=1;i<=m;++i) a[i]+=a[i-1];
    	to[0]=d[0]=b[0]=0;
    	top=0;stk[top++]=0;
    	for (int k=1;k<=day;++k){
    		ll res=0;
    		int last=m,x=max((ll)to[stk[top-1]],min((b[k]-b[stk[top-1]])/(d[k]-d[stk[top-1]]),(ll)m));
    		for (;x<last;x=max((ll)to[stk[top-1]],min((b[k]-b[stk[top-1]])/(d[k]-d[stk[top-1]]),(ll)m))){
    			res+=(d[k]-d[stk[top-1]])*(s[last]-s[x])+(b[stk[top-1]]-b[k])*(a[last]-a[x]);
    			if ((last=x)>to[stk[top-1]]) break;
    			if (!--top) break;
    		}
    		if ((to[k]=last)<m) stk[top++]=k;
    		printf("%lld
    ",res);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    apache php 整合
    ide vim 设置
    saas
    总结一些做人的标准
    关于项目和产品
    Page.ClientScript.RegisterArrayDeclaration
    span或者input的disabled(小技巧)
    JS屏蔽鼠标右键的两种方法(小技巧)
    js使用对象(小技巧)
    各种CMS
  • 原文地址:https://www.cnblogs.com/wangyurzee7/p/5224273.html
Copyright © 2020-2023  润新知