51nod 1624 STL妙用+二分

来源:互联网 发布:法国文化史知乎 编辑:程序博客网 时间:2024/04/30 12:48

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
原创粉丝点击