• 联考20200727 T2 加减




    分析:
    一加一减很烦,我们把函数按长度分奇偶来观察
    发现各自都是一个上凸函数
    (看上去就非常有道理,题解有证明)

    这种上凸函数可以用分治维护,两个凸函数合并可以维护其差分序列,类似归并排序一样的合并
    然后开始分类讨论,每一段区间维护四个凸包,分别是:
    开头为正的奇数下标凸包((odd)
    开头为负的奇数下标凸包((-odd)
    开头为正的偶数下标凸包((even)
    开头为负的偶数下标凸包((-even)
    这里我简便表示一下(
    合并的时候:
    (odd=max{odd_l-even_r,even_l+odd_r})
    (-odd=max{-odd_l+even_r,-even_l-odd_r})
    (even=max{odd_l-odd_r,even_l+even_r})
    (-even=max{-odd_l+odd_r,-even_l-even_r})
    应该。。看得懂吧2333,就是左右以何种方式合并
    (max)是凸函数每个点值都取最大
    一次计算的复杂度是(O(n))的,整体复杂度是(O(nlogn))
    代码。。代码写得太杂乱没调出来,80分。。。Wrong Answer
    dbq我是废物
    这里是垃圾代码,哪位神仙看出错了直接评论区D我就好QAQ

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<set>
    #include<map>
    #include<string>
    
    #define maxn 500005
    #define INF 0x3f3f3f3f
    #define MOD 998244353
    #define eps 1e-10
    
    using namespace std;
    
    inline long long getint()
    {
    	long long num=0,flag=1;char c;
    	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
    	while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
    	return num*flag;
    }
    
    int n;
    long long a[maxn];
    long long P[maxn],M[maxn],tmp1[maxn],tmp2[maxn],nP[maxn],nM[maxn];
    
    inline void solve(int l,int r)
    {
    	if(l==r){P[l]=a[l],M[l]=-a[l];return;}
    	int mid=(l+r)>>1;
    	solve(l,mid),solve(mid+1,r);
    	int p1,p2,p;
    	
    	for(int i=l;i<=r;i++)tmp1[i]=tmp2[i]=-INF;
    	p1=l,p2=mid+1,p=l+1;
    	tmp1[p]=P[p1]+M[p2],p+=2,p1+=2,p2+=2;
    	while(p1<=mid&&p2<=r)
    		if(P[p1]>M[p2])tmp1[p]=P[p1],p+=2,p1+=2;
    		else tmp1[p]=M[p2],p+=2,p2+=2;
    	while(p1<=mid)tmp1[p]=P[p1],p+=2,p1+=2;
    	while(p2<=r)tmp1[p]=M[p2],p+=2,p2+=2;
    	//odd -odd
    	p1=l+1,p2=mid+2,p=l+1;
    	while(p1<=mid&&p2<=r)
    		if(P[p1]>P[p2])tmp2[p]=P[p1],p+=2,p1+=2;
    		else tmp2[p]=P[p2],p+=2,p2+=2;
    	while(p1<=mid)tmp2[p]=P[p1],p+=2,p1+=2;
    	while(p2<=r)tmp2[p]=P[p2],p+=2,p2+=2;
    	//even even
    	for(int i=l+3;i<=r;i+=2)tmp1[i]+=tmp1[i-2],tmp2[i]+=tmp2[i-2];
    	for(int i=l+1;i<=r;i+=2)nP[i]=max(tmp1[i],tmp2[i]);
    	
    	for(int i=l;i<=r;i++)tmp1[i]=tmp2[i]=-INF;
    	p1=l,p2=mid+1,p=l+1;
    	tmp1[p]=M[p1]+P[p2],p+=2,p1+=2,p2+=2;
    	while(p1<=mid&&p2<=r)
    		if(M[p1]>P[p2])tmp1[p]=M[p1],p+=2,p1+=2;
    		else tmp1[p]=P[p2],p+=2,p2+=2;
    	while(p1<=mid)tmp1[p]=M[p1],p+=2,p1+=2;
    	while(p2<=r)tmp1[p]=P[p2],p+=2,p2+=2;
    	//-odd odd
    	p1=l+1,p2=mid+2,p=l+1;
    	while(p1<=mid&&p2<=r)
    		if(M[p1]>M[p2])tmp2[p]=M[p1],p+=2,p1+=2;
    		else tmp2[p]=M[p2],p+=2,p2+=2;
    	while(p1<=mid)tmp2[p]=M[p1],p+=2,p1+=2;
    	while(p2<=r)tmp2[p]=M[p2],p+=2,p2+=2;
    	//-even -even
    	for(int i=l+3;i<=r;i+=2)tmp1[i]+=tmp1[i-2],tmp2[i]+=tmp2[i-2];
    	for(int i=l+1;i<=r;i+=2)nM[i]=max(tmp1[i],tmp2[i]);
    	
    	for(int i=l;i<=r;i++)tmp1[i]=tmp2[i]=-INF;
    	p1=l,p2=mid+2,p=l;
    	tmp1[p]=P[p1],p+=2,p1+=2;
    	while(p1<=mid&&p2<=r)
    		if(P[p1]>M[p2])tmp1[p]=P[p1],p+=2,p1+=2;
    		else tmp1[p]=M[p2],p+=2,p2+=2;
    	while(p1<=mid)tmp1[p]=P[p1],p+=2,p1+=2;
    	while(p2<=r)tmp1[p]=M[p2],p+=2,p2+=2;
    	//odd -even
    	p1=l+1,p2=mid+1,p=l;
    	tmp2[p]=P[p2],p+=2,p2+=2;
    	while(p1<=mid&&p2<=r)
    		if(P[p1]>P[p2])tmp2[p]=P[p1],p+=2,p1+=2;
    		else tmp2[p]=P[p2],p+=2,p2+=2;
    	while(p1<=mid)tmp2[p]=P[p1],p+=2,p1+=2;
    	while(p2<=r)tmp2[p]=P[p2],p+=2,p2+=2;
    	//even odd
    	for(int i=l+2;i<=r;i+=2)tmp1[i]+=tmp1[i-2],tmp2[i]+=tmp2[i-2];
    	for(int i=l;i<=r;i+=2)nP[i]=max(tmp1[i],tmp2[i]);
    	
    	for(int i=l;i<=r;i++)tmp1[i]=tmp2[i]=-INF;
    	p1=l,p2=mid+2,p=l;
    	tmp1[p]=M[p1],p+=2,p1+=2;
    	while(p1<=mid&&p2<=r)
    		if(M[p1]>P[p2])tmp1[p]=M[p1],p+=2,p1+=2;
    		else tmp1[p]=P[p2],p+=2,p2+=2;
    	while(p1<=mid)tmp1[p]=M[p1],p+=2,p1+=2;
    	while(p2<=r)tmp1[p]=P[p2],p+=2,p2+=2;
    	//-odd even
    	p1=l+1,p2=mid+1,p=l;
    	tmp2[p]=M[p2],p+=2,p2+=2;
    	while(p1<=mid&&p2<=r)
    		if(M[p1]>M[p2])tmp2[p]=M[p1],p+=2,p1+=2;
    		else tmp2[p]=M[p2],p+=2,p2+=2;
    	while(p1<=mid)tmp2[p]=M[p1],p+=2,p1+=2;
    	while(p2<=r)tmp2[p]=M[p2],p+=2,p2+=2;
    	//-even -odd
    	for(int i=l+2;i<=r;i+=2)tmp1[i]+=tmp1[i-2],tmp2[i]+=tmp2[i-2];
    	for(int i=l;i<=r;i+=2)nM[i]=max(tmp1[i],tmp2[i]);
    		
    	for(int i=l;i<=r;i++)P[i]=nP[i],M[i]=nM[i];
    	for(int i=r;i>l+1;i--)P[i]=P[i]-P[i-2],M[i]=M[i]-M[i-2];
    }
    
    int main()
    {
    	n=getint();
    	for(int i=1;i<=n;i++)a[i]=getint();
    	solve(1,n);
    	for(int i=3;i<=n;i++)P[i]+=P[i-2];
    	for(int i=1;i<=n;i++)printf("%lld%c",P[i],i==n?'
    ':' ');
    }
    

  • 相关阅读:
    杭电1029--Ignatius and the Princess IV(哈希)
    杭电1465--不容易系列之一
    杭电1021--Fibonacci Again
    杭电5018--Revenge of Fibonacci
    UVa10651(记忆化搜索)
    <Win32_5>深入浅出Win32的计时器
    偷个空,写个博客——各种沟通各种纠结
    Arbitrage HDU
    常用的字符串处理方法
    无法捕获的异常:MissingMethodException
  • 原文地址:https://www.cnblogs.com/Darknesses/p/13386067.html
Copyright © 2020-2023  润新知