bzoj 3613 //3613: [Heoi2014]南园满地堆轻絮 逆序对/二分

bzoj 3613   //3613: [Heoi2014]南园满地堆轻絮   //在线测评地址https://www.lydsy.com/JudgeOnline/problem.php?id=3613
//在线测评地址https://www.luogu.org/problem/P4105

更多题解,详见https://blog.csdn.net/mrcrack/article/details/90228694BZOJ刷题记录

方法一:逆序对

Accepted39884 kb6408 msC++595 B

//3613: [Heoi2014]南园满地堆轻絮
//在线测评地址https://www.lydsy.com/JudgeOnline/problem.php?id=3613
//在线测评地址https://www.luogu.org/problem/P4105
//在提示的帮助下,题意能很快读懂,这个方面,题目出得不错。2019-11-8 10:53
//此文http://zhouzixuan.blog.uoj.ac/blog/772思路不错,摘抄如下
/*
我们发现只有逆序对才会对答案产生影响
我们把所有逆序对提到同一高度即可
显然两个逆序对变成他们的中位数最优
因此我们取逆序对之差的最大值作为答案
最后把答案/2即可
*/
//2^31-1=2147483647
//样例通过,提交Wrong_Answer    20352 kb    616 ms    C++/Edit    554 B   2019-11-9 17:23
//看了数据范围,对于 100% 的数据, n≤5000000n≤5000000n≤5000000,Sa,Sb,Sc,Sd,A[1]≤10000S_a,S_b,S_c,S_d,A[1] ≤10000Sa​,Sb​,Sc​,Sd​,A[1]≤10000,Mod≤1000000007 Mod≤1000000007 Mod≤1000000007
//没有long long应该过不了,做人不能太扣。2019-11-9 17:27
//将int改成long long
//修改,样例通过,提交AC.2019-11-9 17:30
#include <stdio.h>
#define LL long long
#define maxn 5000100
LL n,sa,sb,sc,sd,a[maxn],mod;
LL max(LL a,LL b){
    return a>b?a:b;
}
LL f(LL x){
    return (sa*x%mod*x%mod*x%mod+sb*x%mod*x%mod+sc*x%mod+sd)%mod;
}
LL A(int i){
    return (f(a[i-1])+f(a[i-2]))%mod;
}
int main(){
    int i;
    LL maxt=0,ans=0;
    a[0]=0;
    scanf("%lld%lld%lld%lld%lld%lld%lld",&n,&sa,&sb,&sc,&sd,&a[1],&mod);
    for(i=2;i<=n;i++)a[i]=A(i);
    for(i=1;i<=n;i++){
        maxt=max(maxt,a[i]);
        ans=max(ans,maxt-a[i]);
    }
    printf("%lld\n",(ans+1)/2);
    return 0;
}

方法二:二分

Accepted39884 kb7864 msC++/Edit884 B

//二分,此文https://blog.csdn.net/regina8023/article/details/45555479代码写得真不错,思路摘抄如下
/*
二分。
二分这个最大值,如何判断值m
是否成立?
从1到n判断,使得当前满足条件的值pre
尽可能小,如果a[i+1]+m还小于pre,这个m值一定不成立。
*/
//样例通过,提交AC.2019-11-9 19:33
#include <stdio.h>
#define LL long long
#define maxn 5000100
LL n,sa,sb,sc,sd,a[maxn],mod,ans;
LL f(LL x){
    return (sa*x%mod*x%mod*x%mod+sb*x%mod*x%mod+sc*x%mod+sd)%mod;
}
LL A(int i){
    return (f(a[i-1])+f(a[i-2]))%mod;
}
int judge(LL x){
    LL pre=a[1]-x;//pre   改变后的a[1]值
    int i;
    for(i=2;i<=n;i++)
        if(pre<=a[i]+x){
            if(pre<a[i]-x)pre=a[i]-x;//此处错写成if(pre<a[i]+x)pre=a[i]+x;//pre   改变后的a[i]值
        }else return 0;
    return 1;//x有用
}
void bisection(){
    LL l,r,mid;
    l=0,r=mod-1;
    while(l+1<r){
        mid=(l+r)/2;
        if(judge(mid))r=mid;
        else l=mid;
    }
    ans=r;
}
int main(){
    int i;
    a[0]=0;
    scanf("%lld%lld%lld%lld%lld%lld%lld",&n,&sa,&sb,&sc,&sd,&a[1],&mod);
    for(i=2;i<=n;i++)a[i]=A(i);
    bisection();
    printf("%lld\n",ans);
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值