TMOOC 1969 開鎖
阿新 • • 發佈:2019-03-30
name cst 由於 就是 自己的 tro 限制 sin 替換
但是小明沒有算到的是,小小明來到了小韓隆家做客,他改變了密碼鎖的密碼。現在密碼是這樣構造的:從n個數字中任選一段數字I到 r,從其中任選一個數 X,將這一段數的次大值與 x 異或起來得到y。鎖的密碼就是所有y值中的最大值。因為你十分討厭小明,不想讓他大力出這個密碼,所以你要算出小小明改完之後,這個鎖的密碼是多少,方便誤導小明。
對於100%的數據:1<=n<=50000,1<=a[i]<=10^9,保證a[i]兩兩不同。
TMOOC 1969 開鎖
題目描述
(時間限制:1000ms 內存限制:51200KB)
小明經過千辛萬苦,終於來到了 小韓隆的門前。但是小韓隆早有防備,將自己的門鎖換成了密碼鎖。密碼鎖上有n個數字和一個輸入裝置。這n個數字是小韓隆刻在鎖上的,看來需要解謎了。小明知道小韓隆十分喜歡異或,於是他猜想,這個裝置應該是由兩個數異或而成。通過小弟們對鄰居的詢問,小明知道了這個密碼是由如下方法構造出的:從n個數字中任選一段數字I到 r,從其中任選一個數X,將這一段數的最大值與x異或起來得到y。鎖的密碼就是所有y值中的最大值。小明冥思苦想了幾個小時,終於發現:因為l、r、x都是他自己選的,所以得到的y值會有很多個。由於小明受到NOIP的打擊,十分厭惡“大力出奇跡”,他不想再一個一個試密碼。現在他找到了作為小弟的你,想要你告訴他鎖的密碼是多少。
輸入樣例
5
9 2 1 4 7
輸出樣例
14
樣例解釋
第一個樣例l=1,r=5,選取的x為9,密碼為7^9=14。
第二個樣例1=1,r=4,選取的x為9,密碼為4^9=13。另一種可行的方案是1=1,r=4,選取的x為9,密碼同樣為4^9=13。
數據範圍
對於40%的數據:n<=5000。
思路
設f[i][j][0]
為從i~j的最大值、f[i][j][1]
為從i~j的次大值。
那麽,對於任意i~j,a[i]來說,
- 如果
a[i]>f[i][j-1][0]
,那麽f[i][j][1]=f[i][j-1][0]
、f[i][j][0]=a[i]
(順位下沿),可以異或的y值為a[i]^a[j...i-1]
。 - 否則如果
a[i]>f[i][j-1][1]
,那麽f[i][j][1]=a[i]
(替換次大),可以異或的y值為a[i]^a[j...i-1]
。 - 否則,那麽
f[i][j][0]=f[i][j-1][0]
f[i][j][1]=f[i][j-1][1]
,可以異或的y值為f[i][j][1]^a[i]
(剩下的異或已經處理一遍了)。
但是,這道題N的範圍是50000,開f[50000][50000][2]
空間肯定會炸。
考慮到第二維度的值只是當前處理的j,可以使用滾動數組降維。
設f[i][0]
為從i~(當前的j)的最大值、f[i][1]
為從i~(當前的j)的次大值。既可解決空間不足的問題。
參考代碼
水過了。
#include <cstdio>
#include <cmath>
using namespace std;
int n,a[10001],f[10001][2],ans;
int main() {
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",a+i);
for(int i=2;i<=n;i++){
for(int j=1;j<i;j++){
if(a[i]>f[j][0]){
f[j][1]=f[j][0];
f[j][0]=a[i];
for(int k=j;k<i;k++)ans=ans>(a[k]^a[i])?ans:a[k]^a[i];
}else if(a[i]>f[j][1]){
f[j][1]=a[i];
for(int k=j;k<i;k++)ans=ans>(a[k]^a[i])?ans:a[k]^a[i];
}else{
ans=ans>(f[j][1]^a[i])?ans:(f[j][1]^a[i]);
}
}
}
printf("%d",ans);
}
TMOOC 1969 開鎖