zoukankan      html  css  js  c++  java
  • BZOJ 5424: 烧桥计划

    BZOJ 5424: 烧桥计划

    目前暂居rk1QAQ

    首先,设(f[i][k])为前i个点中,选了第i个点,总共选了k个点的答案。那么就有:

    [f[i][k]=min_{j<i}{f[j][k-1]+calc(j,i)}+k*a[i] ]

    其中,(calc(j,i)=[s[i-1]-s[j]>m]*(s[i-1]-s[j]))

    那么转移的时候,大于m的很显然的可以用前缀和,而小于等于m的可以用单调队列处理。这样转移复杂度就变成了(O(n^2))

    (1000 le a_ile 2000),那么就设选的最小的k个点,k个点的贡献就是(frac{k*(k-1)}{2}1000),而如果一个点也不选,那么贡献最大是(2000n),可以发现,当(kge sqrt{n})的时候,选一定不会更优了,所以只需要转移大约(sqrt n)次就好了。

    然后转移151次会WA,而转移152次就能A掉了,所以。。。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<cctype>
    #define qmin(x,y) (x=min(x,y))
    #define qmax(x,y) (x=max(x,y))
    #define vi vector<int>
    #define vit vector<int>::iterator
    #define pir pair<int,int>
    #define fr first
    #define sc second
    #define mp(x,y) make_pair(x,y)
    #define rsort(x,y) (sort(x,y),reverse(x,y))
    using namespace std;
    
    inline char gc() {
    //	static char buf[100000],*p1,*p2;
    //	return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
    	return getchar();
    }
    
    template<class T>
    int read(T &ans) {
    	ans=0;char ch=gc();T f=1;
    	while(!isdigit(ch)) {
    		if(ch==EOF) return -1;
    		if(ch=='-') f=-1;
    		ch=gc();
    	}
    	while(isdigit(ch))
    		ans=ans*10+ch-'0',ch=gc();
    	ans*=f;return 1;
    }
    
    template<class T1,class T2>
    int read(T1 &a,T2 &b) {
    	return read(a)!=EOF&&read(b)!=EOF?2:EOF;
    }
    
    template<class T1,class T2,class T3>
    int read(T1 &a,T2 &b,T3 &c) {
    	return read(a,b)!=EOF&&read(c)!=EOF?3:EOF;
    }
    
    typedef long long ll;
    const int Maxn=110000;
    const int inf=0x3f3f3f3f;
    
    int n,m,a[Maxn],s[Maxn],f[Maxn],l,r,cur,g[Maxn];
    pir p[Maxn];
    
    void push(int x,int y) {
    	pir now=mp(x,y);
    	while(r>=l&&p[r]>now) r--;
    	p[++r]=now;
    }
    
    int front() {
    	while(p[l].sc<cur) l++;
    	return p[l].fr;
    }
    
    signed main() {
    //	freopen("test.in","r",stdin);
    	read(n,m);
    	if(m<0) m=0;
    	for(int i=1;i<=n;i++)
    		read(a[i]);
    	n++;
    	for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i];
    	int ans=inf,cnt=1;
    	memset(f,0x3f,sizeof(f));
    	f[0]=0;
    	for(int i=1;i<=n;i++) g[i]=s[i];
    //	memset(g,0x3f,sizeof(g));
    //	for(int i=1;i<=n;i++) f[i]=g[i]=inf;
    	for(int i=1;i<=152;i++) {
    		r=0,l=1;
    		cur=0;
    		push(0,0);
    		int temp=inf;
    		for(int i=1;i<=n;i++) {
    			while(s[i-1]-s[cur]>m) qmin(temp,g[cur]-s[cur]),cur++;
    			int sxz=f[i];
    			f[i]=s[i-1]+temp;
    			qmin(f[i],front());
    			push(sxz,i);
    			f[i]+=cnt*a[i];
    		}
    		qmin(ans,f[n]);
    		memcpy(g,f,sizeof(g));
    		cnt++;
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    
    
    
    
  • 相关阅读:
    论登陆博客园的时候忘记了密码
    LNOI 2019 旁观记
    [bzoj3790] 神奇项链
    [POI2000] 病毒
    [HAOI2008] 移动玩具
    [codevs1288] 埃及分数
    [hdu1401] Solitaire
    [洛谷P3806] [模板] 点分治1
    [国家集训队] 聪聪可可
    [洛谷P4178] Tree
  • 原文地址:https://www.cnblogs.com/shanxieng/p/10502447.html
Copyright © 2011-2022 走看看