• 洛谷 P5665 划分


    洛谷 P5665 划分

    https://www.luogu.com.cn/problem/P5665

    2s,1GB

    Snipaste_2020-06-23_21-53-44.png

    Snipaste_2020-06-23_21-54-01.png

    Snipaste_2020-06-23_21-54-11.png

    Tutorial

    https://www.luogu.com.cn/blog/syksykCCC/solution-p5665

    1

    假设 (sumL+x le sumR) ,那么我们将 (x) 分到那一段更优呢.

    考虑 ((sum+x)^2 = sum^2+x^2+2x cdot sum) .也就是说,将其分至左边更优.

    也就说,我们贪心的令最后一段尽量短即可.

    (g_i) 表示 ([1,i]) 的最优策略中最后一段为 ((g_i,i]) .

    那么我们对于 (i) ,想要找出最大的 (j) ,满足 (s_i - s_j ge s_j-s_{g_j}) 作为 (g_i) .

    将式子变形得到 (s_i ge 2s_j-s_{g_j}) .那么可以用单调队列来维护 ((j,2s_j-s_{g_j})) .就可以 (O(n)) 得到 (g_i) .

    然后就可以利用 (g) 求解答案了.

    Code

    #include <cassert>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #define debug(...) fprintf(stderr,__VA_ARGS__)
    using namespace std;
    inline char nc() {
    //	return getchar();
    	static char buf[100000],*l=buf,*r=buf;
    	return l==r&&(r=(l=buf)+fread(buf,1,100000,stdin),l==r)?EOF:*l++;
    }
    template<class T> void read(T &x) {
    	x=0; int f=1,ch=nc();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=nc();}
    	while(ch>='0'&&ch<='9'){x=x*10-'0'+ch;ch=nc();}
    	x*=f;
    }
    typedef long long ll;
    const int maxn=4e7+50;
    const int maxm=1e5+50;
    const int base=1e9;
    int n,type;
    int g[maxn];
    int q[maxn]; 
    ll s[maxn],val[maxn];
    void write(__int128 x) {
    	if(x==0) return;
    	write(x/10),printf("%d",int(x%10)); 
    }
    int main() {
    	read(n),read(type);
    	if(type==0) {
    		for(int i=1;i<=n;++i) read(s[i]),s[i]+=s[i-1];
    	}
    	else {
    		ll x,y,z,m,mod=1<<30;
    		read(x),read(y),read(z),read(s[1]),read(s[2]),read(m);
    		for(register int i=3;i<=n;++i) s[i]=(x*s[i-1]+y*s[i-2]+z)%mod;
    		for(register int j=1,i=1;j<=m;++j) {
    			int p,l,r; read(p),read(l),read(r),r=r-l+1;
    			while(i<=p) s[i]=s[i-1]+s[i]%r+l,++i;
    		}
    	}
    	int hd=0,tl=-1;
    	q[++tl]=0;
    	for(register int i=1;i<=n;++i) {
    		while(hd<tl&&val[q[hd+1]]<=s[i]) ++hd;
    		g[i]=q[hd],val[i]=2*s[i]-s[g[i]];
    		while(hd<tl&&val[q[tl]]>=val[i]) --tl;
    		q[++tl]=i;
    	}
    	__int128 an=0;
    	for(int u=n;u;u=g[u]) {
    		__int128 t=val[u]-s[u];
    		an=an+t*t;
    	}
    	write(an);
    	return 0; 
    } 
    
  • 相关阅读:
    os.fork()
    解决方案:WindowsError: [Error 2]
    Python遍历文件夹和读写文件的方法
    导航帖
    IDEA后缀补全及快捷键
    Codeforces-Round#614 Div2
    图论算法-欧拉回路 专题训练
    快速求出n!质因数的个数
    Codeforces-Round#589 Div2
    洛谷P3386二分图匹配
  • 原文地址:https://www.cnblogs.com/ljzalc1022/p/13184854.html
Copyright © 2020-2023  润新知