1. 程式人生 > >【17.12.22.B】

【17.12.22.B】

man name 技術 ~~ stream ios include def 輸入

B

題面描述:

給一個長度為n的序列,a[1], a[2], ... , a[n], 選出連續的k個數,使得這k個數的最大值加這k個數的or值最大。

假設選出的數為a[l], a[l + 1], ... , a[l + k -1],即求

max(a[l], a[l + 1], ... , a[l + k -1]) + (a[l] | a[l + 1] | ... | a[l + k -1])

對於所有的1 <= k <= n,輸出答案

輸入:

第一行輸入一個n,第二行輸入n個數,a[1], a[2], ... , a[n].

輸出:

輸出n行,每行一個整數。第

i行表示k = i時的答案。

樣例輸入:

3

1 0 2

樣例輸出:

4

4

5

對於20%的數據,1 <= n <= 300

對於40%的數據,1 <= n <= 5000

對於100%的數據,1 <= n <= 200000, 0 <= a[i] < 2^16

【題解】

①註意到2^16了嗎,有趣的地方就在這裏了。

②結合|和+的定義我們可以知道,定義f[i]表示長度長度為i的序列的值最大,那麽f[i]≥f[i-1];

③考慮求f[i],如果一個區間對我們的答案有貢獻,那麽區間的左右一定是最大值或能使異或值改變的值,而兩邊都是最大值的話去掉一個也無所謂,所以兩邊必定有一個能改變異或值的。

④可以做到了,枚舉左右端點,然後維護其能改變其異或值的位置,最多16個,轉移即可!

(建議看代碼)

技術分享圖片
 1 /*3
 2 1 0 2
 3 好想用linux啊~
 4 其實代碼很簡單,但是思路很~~怎麽說呢
 5 精巧吧;
 6 註意到|和+的單調 ,還有2^16這個數,很容易想到按位搞事情
 7 其實自己是想到前半部分的,但是經驗不夠,不知道怎麽運用,積累重要。 
 8 */
 9 #include <cstdio>
10 #include <iostream>
11 #include <cstring>
12
#include <algorithm> 13 #include <queue> 14 #include <vector> 15 #include <ctime> 16 #include <cmath> 17 #define inf 0x3f3f3f3f 18 #define ll long long 19 #define N 200010 20 #define mem(f,a) memset(f,a,sizeof(f)) 21 #define Run(i,l,r) for(int i=l;i<=r;i++) 22 #define Don(i,l,r) for(int i=l;i>=r;i--) 23 #define Eun(i,u,E) for(int i=head[u],v=E[i].v;i!=-1;i=E[i].next,v=E[i].v) 24 using namespace std; 25 int n,a[N],pre[N],num[N],s[N],top,ans[N]; 26 void solve() 27 { mem(pre,0); mem(num,0); top=0; 28 Run(i,1,n){ 29 while (top&&a[s[top-1]]<=a[i]) top--; 30 s[top++]=i; 31 Run(j,0,15){ 32 if (a[i]&(1<<j)) { 33 pre[j]=i; 34 num[i]=a[i]; 35 } 36 else num[pre[j]]|=a[i]; 37 } 38 Run(j,0,15)if (pre[j]){ 39 int l=0,r=top-1; 40 while (l<r){ 41 int mid=(l+r)/2; 42 if (s[mid]>=pre[j]) r=mid; 43 else l=mid+1; 44 } 45 int maxn=a[s[l]]; 46 ans[i-pre[j]+1]=max(ans[i-pre[j]+1],maxn+num[pre[j]]); 47 } 48 } 49 } 50 int main() 51 { freopen("B.in","r",stdin); 52 freopen("B.out","w",stdout); 53 scanf("%d",&n); 54 Run(i,1,n){ 55 scanf("%d",&a[i]); 56 } 57 solve(); 58 Run(i,1,n/2) a[i]=a[n-i+1]; 59 solve(); 60 Run(i,1,n){ 61 ans[i]=max(ans[i-1],ans[i]); 62 printf("%d\n",ans[i]); 63 } 64 return 0; 65 }//by tkys_Austin;
View Code

【17.12.22.B】