zoukankan      html  css  js  c++  java
  • [Noip2019]划分

    [Noip2019]划分

    一.前言

    ​ 没保存哭了……重写。呕这该死的高精度,dev-c++,lemon,int128,O2,给我人都整傻了。本文不带高精度喔。题目链接

    二.思路

    ​ 首先我们可以找到一些奇奇怪怪的dp,这之中较为突出的是 (f[i][j]=min{f[k][j]+(sum[i]-sum[j])^2}).但是!我们先不管他好吧。

    ​ 根据和平方大于平方和的基本不等式来看,我们追求划分的段尽量多。而题目又有一个划分的每一段的和不下降的条件,很容易能想到最后一段越小,能划的段就越多(因为所有总和一定,都是段和)。于是乎我们每次追求转移的时候((sum[i]-sum[j])^2)的值最小,然后划掉平方,也就是使得段和最小。

    ​ 由于前缀和不降,所以 j 尽量靠近 i (要大要小很难办w)(设段和为 (sig) )希望在 (sum[i]-sum[j]>=sig[j]) 的前提之下 j 尽量大,移项使得 (sum[i]>=sig[j]+sum[j]) 于是维护一个单调上升的队列就行。

    三.CODE

    #include <cstdio>
    #include <iostream>
    #include <cmath>
    #include <string>
    #include <cstring>
    #include <vector>
    #include <algorithm>
    using namespace std;
    #define m_for(i,a,b) for(int i=a;i<=b;++i)
    int read(){
    	char ch=getchar();
    	int res=0,f=1;
    	for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    	for(;ch>='0'&&ch<='9';ch=getchar())res=res*10+(ch-'0');
    	return res*f;
    }
    const int MAXN=4*1e7;
    int n,type,a[MAXN],dd[MAXN],head,tail,pre[MAXN];
    long long sum[MAXN],sig[MAXN];
    long long x,y,z,b[4],m;
    void pt(__int128 a){
        static int st[55];
        while(a){
            st[++st[0]]=a%10;
            a/=10;
        }
        while(st[0])printf("%d",st[st[0]--]);
    }
    int main(){
    	n=read();type=read();
    	if(!type)m_for(i,1,n)a[i]=read();
    	else{
    		x=read();
    		y=read();
    		z=read();
    		b[1]=read();
    		b[2]=read();
    		m=read();
    		for(int i=1,last=0,p,l,r;i<=m;++i)
    		{
    			p=read();
    			l=read();
    			r=read();
    			for(int j=last+1;j<=p;++j)
    			{
    				if(j>2)
    				{
    					b[3]=((long long)x*b[2]+(long long)y*b[1]+z)&((1 << 30) - 1);
    					b[1]=b[2];
    					b[2]=b[3];
    					a[j]=b[3]%(r-l+1)+l;
    				}	
    				else a[j]=b[j]%(r-l+1)+l;
    			}
    			last=p;
    		}
    	}
    	m_for(i,1,n)sum[i]=sum[i-1]+1LL*a[i];
    	m_for(i,1,n){
    		while(head<tail&&sig[dd[head+1]]+sum[dd[head+1]]<=sum[i])++head;
    		sig[i]=sum[i]-sum[dd[head]];
    		pre[i]=dd[head];
    		while(head<tail&&sig[dd[tail]]+sum[dd[tail]]>=sig[i]+sum[i])--tail;
    		dd[++tail]=i;
    	}
    	__int128 ans=0LL;
    	int now=n;
    	while(now){
    		ans+=__int128(sig[now])*sig[now];
    		now=pre[now];
    	}
    	pt(ans);
    	return 0;
    }
    

    我无论是手写高精还是__int128 都用不起,只有 88 分,就酱。

  • 相关阅读:
    校赛writeup
    memory-300——Jarvis OJ
    校赛_warmup_pwn
    sctf
    iscc-pwn1
    level3-64——Jarvis OJ
    JarvisOJ——level2
    JarvisOJ——guestbook
    Javris oj——level0
    linux 服务器 tomcat环境部署出错 重启
  • 原文地址:https://www.cnblogs.com/clockwhite/p/13493540.html
Copyright © 2011-2022 走看看