P4105 [HEOI2014]南园满地堆轻絮

洛谷传送门

\(O(n\log n)\) 的做法讲的人比较多,就不提了()

Solution

因为 \(O(n)\) 的做法并没有看出来正确性显然,所以这里简单yy一下。

我们先说结论:答案为 \((最大逆序对差+1)/2\),也就是将相差最大的逆序对变为同一个数的代价。

\(a_i,a_j(i<j,a_i>a_j)\) 为相差最大的逆序对,那么在区间 \((i,j)\) 中的数一定是大于等于 \(a_j\) 且小于等于 \(a_i\) 的。

那么将区间 \((i,j)\) 全部变为同一个数必然是满足条件的。然后对于 \((1,i)\)\((j,n)\) 这两个区间我们可以用同一种方法去处理。

yy完毕。

Code

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;
const int N=5e6+10,INF=0x3f3f3f3f;
int n,sa,sb,sc,sd,a[N],mod,mx=-INF,ans;

template<typename T>inline void read(T &x){
    x=0; bool f=0;
    char ch=getchar();
    while(!isdigit(ch)){if(ch=='-') f=1;ch=getchar();}
    while(isdigit(ch)){x=x*10+(ch^48);ch=getchar();}
    if(f) x=-x;
}

inline int add(int a,int b){return a+b>mod?a+b-mod:a+b;}
inline int mul(int a,int b){return 1ll*a*b%mod;}

inline int f(int x){	//这里有点毒瘤,不过问题不大(●'◡'●)
    return add(add(add(mul(mul(mul(sa,x),x),x),mul(mul(sb,x),x)),mul(sc,x)),sd);
}

int main(){
    read(n); read(sa); read(sb); read(sc); read(sd); read(a[1]); read(mod);
    for(int i=2;i<=n;i++) a[i]=add(f(a[i-1]),f(a[i-2]));
    for(int i=1;i<=n;i++){
        if(mx<=a[i]) mx=a[i];
        else ans=max(ans,mx-a[i]+1>>1);
    }
    printf("%d\n",ans);
    return 0;
}
posted @ 2020-12-17 20:49  jasony_sam  阅读(75)  评论(0编辑  收藏  举报