51nod 1624 STL妙用+二分

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1624

这是算法马拉松一道题。当时想法方向是正确的可惜没有想到STL。

题意3*n的矩阵。。要走出一条取余最大路。。

看到3肯定是在这里做文章。。那么可以枚举第一行二分剩下的嘛。。

到这里思路都很清晰,但是考虑到如果不删除(删除当前节点不合法的走法,移动一下删一个)的话,二分就结果不一定正确了。。这就十分尴尬

赛后看题解可以 multiset来删除,当然也可以map了。。。这里就是经验的问题了


二分时候要注意一些地方,一个最优答案当然是靠近P-1了,那么枚举的x怎么靠近P-1呢,当然有两种方法,一是x+y靠近p-1,要么是x+y靠近2*p-1了。

然后在multiset里面二分即可。。

这里要学习stl的应用,自己根本没有领会到stl的精髓啊。。。蒟蒻加油!

#include <iostream>
#include <set>
#include <stdio.h>
#include <algorithm>
#include <fstream>
using namespace std;

const int maxn=100005;
long long n,p;
long long arr[3][maxn];
long long sum[3][maxn];
multiset<int> s;
int main()
{
    scanf("%d%d",&n,&p);
    for(int i=0;i<3;i++){
        for(int j=0;j<n;j++){
            scanf("%d",&arr[i][j]);
            arr[i][j]=arr[i][j]%p;
        }
    }
    sum[0][0]=arr[0][0]%p;
    sum[0][1]=arr[0][1]%p;
    sum[0][2]=arr[0][2]%p;
    for(int i=0;i<3;i++){
        for(int j=1;j<n;j++){
            sum[i][j]=(sum[i][j-1]+arr[i][j])%p;
        }
    }
    for(int j=0;j<n;j++){
        s.insert(-((sum[1][j]+sum[2][n-1]-sum[2][j]+arr[2][j]+p+p)%p));
    }
    int ans=0;
    int x;
    multiset<int>::iterator it;
    for(int i=0;i<n;i++){
        it=s.lower_bound(-(p-1-(sum[0][i]-sum[1][i]+arr[1][i]+p+p)%p));
        if(it!=s.end())
        x=(sum[0][i]-sum[1][i]+arr[1][i]-*it+p+p)%p;
        it=s.lower_bound(-(p+p-1-(sum[0][i]-sum[1][i]+arr[1][i]+p+p)%p));
        if(it!=s.end())
        x=max((sum[0][i]-sum[1][i]+arr[1][i]-*it+p+p)%p,(long long)x);
        s.erase(s.find(-((sum[1][i]+sum[2][n-1]-sum[2][i]+arr[2][i]+p+p)%p)));
        ans=max(ans,x);
    }
    printf("%d",ans);
    return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值