1. 程式人生 > >1624 取余最長路(set)

1624 取余最長路(set)

splay 遊戲 困難 %d closed algo const sstream lis

1624 取余最長路

基準時間限制:1 秒 空間限制:131072 KB 分值: 40 難度:4級算法題

佳佳有一個n*m的帶權矩陣,她想從(1,1)出發走到(n,m)且只能往右往下移動,她能得到的娛樂值為所經過的位置的權的總和。

有一天,她被下了惡毒的詛咒,這個詛咒的作用是將她的娛樂值變為對p取模後的值,這讓佳佳十分的不開心,因為她無法找到一條能使她得到最大娛樂值的路徑了!

她發現這個問題實在是太困難了,既然這樣,那就只在3*n的矩陣內進行遊戲吧!

現在的問題是,在一個3*n的帶權矩陣中,從(1,1)走到(3,n),只能往右往下移動,問在模p意義下的移動過程中的權總和最大是多少。


樣例解釋:

移動的方案為“下下右”。

Input

單組測試數據 第一行兩個數n(1<=n<=100000),p(1<=p<=1000000000)。 接下來3行,每行n個數,第i行第j列表示a[i][j]表示該點的權(0<=a[i][j]<p)。

Output

一個整數表示答案。

Input示例

2 3

2 2

2 2

0 1

Output示例

2

//以前竟然都沒遇到過,set中竟然也有lower_bound(x) ,可以返回最小的大於等於 x 的叠代器

iterator lower_bound( const key_type &key ): 返回一個叠代器,指向鍵值>

= key的第一個元素。

iterator upper_bound( const key_type &key ):返回一個叠代器,指向鍵值> key的第一個元素。

先碼住,這題,很容易想到 N^2 解法,然而只需要枚舉其中一個拐點即可,另一部分二分得出

技術分享
 1 # include <cstdio>
 2 # include <cstring>
 3 # include <cstdlib>
 4 # include <iostream>
 5 # include <vector>
 6 # include <queue>
 7
# include <stack> 8 # include <map> 9 # include <bitset> 10 # include <sstream> 11 # include <set> 12 # include <cmath> 13 # include <algorithm> 14 using namespace std; 15 # define LL long long 16 # define pr pair 17 # define mkp make_pair 18 # define lowbit(x) ((x)&(-x)) 19 # define PI acos(-1.0) 20 # define INF 0x3f3f3f3f3f3f3f3f 21 # define eps 1e-8 22 # define MOD 1000000007 23 24 inline LL scan() { 25 LL x=0,f=1; char ch=getchar(); 26 while(ch<0||ch>9){if(ch==-) f=-1; ch=getchar();} 27 while(ch>=0&&ch<=9){x=x*10+ch-0; ch=getchar();} 28 return x*f; 29 } 30 inline void Out(int a) { 31 if(a<0) {putchar(-); a=-a;} 32 if(a>=10) Out(a/10); 33 putchar(a%10+0); 34 } 35 # define MX 100005 36 /**************************/ 37 38 int n,p; 39 LL sum[3][MX]; 40 41 int main() 42 { 43 n=scan(); p=scan(); 44 for (int i=0;i<3;i++) 45 { 46 for (int j=1;j<=n;j++) 47 { 48 sum[i][j]=scan(); 49 sum[i][j]=(sum[i][j]+sum[i][j-1])%p; 50 } 51 } 52 int ans = (sum[0][1]+sum[1][1]+sum[1][n])%p; 53 set<int> s; 54 for (int i=1;i<=n;i++) 55 { 56 int tp = (sum[0][i]-sum[1][i-1]+p)%p; 57 s.insert( tp ); 58 int dat = (sum[1][i]+sum[2][n]-sum[2][i-1]+p)%p; 59 set<int>::iterator it = s.lower_bound(p-dat); 60 if (it!=s.end()) 61 { 62 if (it!=s.begin()) 63 { 64 it--; 65 ans = max((LL)ans,(*it+sum[1][i]+sum[2][n]-sum[2][i-1]+p)%p); 66 } 67 } 68 } 69 printf("%d\n",ans); 70 return 0; 71 }
View Code

1624 取余最長路(set)