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;
}