【bzoj1318】[Spoj744] Longest Permutation(亂搞)
阿新 • • 發佈:2018-06-11
esp 個數 urn one sed clas algo 更新 display
題目傳送門:https://www.lydsy.com/JudgeOnline/problem.php?id=1318
這道題的大意是要求一個長度為len,並包含1~len所有數,並使len最大的子區間。開始看題的時候一臉懵逼(好像可以二分?),然後寫到一半突然發現二分有反例。
於是上網搜了一波題解。
正確解法:
我們可以發現這個區間必定滿足這樣的性質:假設它的長度為len,則區間內最大值為len,區間內所有數的和為(len+1)*len/2,並且區間內所有數兩兩不相等。
因為區間內一定包含1,所以我們可以以1為界點劃分整個序列。然後我們假設區間內的最大值在1的左側,於是從當前的1開始向左枚舉,並把從當前枚舉到的數到1之間的最大值作為區間的長度,然後用上面的法則判斷該區間是否合法。因為求區間和明顯比區間最大值方便,所以我們就用前綴和求出當前區間的和來判斷。判斷區間裏是否有相同的數,只需維護一個nxt數組,每個數右邊第一個相同的數出現的位置,然後一邊枚舉一邊更新合法區間的右端點(即與區間內的數有沖突的最左邊一個數)。
代碼:
#include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<ctime> #include<algorithm> #include<queue> #include<vector> #include<map> #define ll long long #define ull unsigned long long #define max(a,b) (a>b?a:b) #definebzoj1318min(a,b) (a<b?a:b) #define lowbit(x) (x& -x) #define mod 1000000007 #define inf 0x3f3f3f3f #define eps 1e-18 #define maxn 1000020 inline ll read(){ll tmp=0; char c=getchar(),f=1; for(;c<‘0‘||‘9‘<c;c=getchar())if(c==‘-‘)f=-1; for(;‘0‘<=c&&c<=‘9‘;c=getchar())tmp=(tmp<<3)+(tmp<<1)+c-‘0‘; return tmp*f;} inline ll power(ll a,ll b){ll ans=0; for(;b;b>>=1){if(b&1)ans=ans*a%mod; a=a*a%mod;} return ans;} inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} using namespace std; int a[maxn],nxt[maxn]; int last[maxn]; ll sum[maxn]; int n; int work(int n) { memset(last,0,sizeof(last)); memset(nxt,0,sizeof(nxt)); for(int i=1;i<=n;i++){ sum[i]=sum[i-1]+a[i]; if(last[a[i]])nxt[last[a[i]]]=i; last[a[i]]=i; } for(int i=1;i<=n;i++)if(!nxt[i])nxt[i]=n+1; int ans=0; for(int i=1;i<=n;i++) if(a[i]==1){ ans=max(ans,1); if(i==1)continue; int r=nxt[i],mx=1; for(int j=i-1;j>0&&a[j]!=1;j--){ r=min(r,nxt[j]); mx=max(mx,a[j]); if(j+mx<=r&&sum[j+mx-1]-sum[j-1]==1ll*(mx+1)*mx/2)ans=max(ans,mx); } } return ans; } int main() { n=read(); for(int i=1;i<=n;i++)a[i]=read(); int ans1=work(n); for(int i=1;i*2<=n;i++){ int tmp=a[i]; a[i]=a[n-i+1]; a[n-i+1]=tmp; } int ans2=work(n); printf("%d\n",max(ans1,ans2)); return 0; }
【bzoj1318】[Spoj744] Longest Permutation(亂搞)