【習題 8-16 UVA - 1618】Weak Key
阿新 • • 發佈:2018-02-20
mes 情況 href ack open down sync mark with
是否成立就好
【鏈接】 我是鏈接,點我呀:)
【題意】
在這裏輸入題意
【題解】
枚舉N[q]和N[r]的位置
因為N[q]是最大值,且N[r]是最小值。
且它們是中間的兩個。
枚舉這兩個可以做到不重復枚舉。
然後假設我們枚舉了q和r的位置分別為i和j
(a[i]>a[j]
那麽我們接下來需要得到兩個東西。
1.在j的右邊找到一個盡可能大的且小於a[i]的數字dp[0][i][j];
2.在i的左邊找到一個盡可能小且大於a[j]的數字dp[1][i][j]。
然後判斷一下dp[0][i][j]> a[j] && dp[1][i][j]< a[i] && dp[0][i][j] > dp[1][i][j]
還要考慮a[i]<a[j]的情況(有兩種情況之一成立都是弱鍵。
方便起見。
直接把原數組翻轉一下。
就會發現用上面說的思路重新做一遍就可以了。
dp[0..1][i][j]這兩個數組可以用一個set.在\(O(N^2*log_2N)\)的復雜度下得到。
【代碼】
/*
dp1[i][j] 表示 j右邊 大於a[j]且小於a[i]的
最大數字
->小於a[i]的最大數字
dp2[i][j] 表示i左邊 大於a[j]且最小的數字
for (int j = n;j >= 1;j--){
}
*/
#include <bits/stdc++.h>
#define ll long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define all(x) x.begin(),x.end()
#define pb push_back
#define ls l,mid,rt<<1
#define rs mid+1,r,rt<<1
using namespace std;
const double pi = acos(-1);
const int dx[4 ] = {0,0,1,-1};
const int dy[4] = {1,-1,0,0};
const int N = 5e3;
set<int> myset;
int n,a[N+10],dp[2][N+10][N+10];
bool solve(){
myset.clear();
rep2(j,n,1){
rep2(i,j-1,1)
if (a[i]>a[j]){
auto temp = myset.upper_bound(a[i]);
if (temp==myset.begin()) {
dp[0][i][j] = 0;
continue;
}
temp--;
dp[0][i][j] = (*temp);
}
myset.insert(a[j]);
}
myset.clear();
rep1(i,1,n){
rep1(j,i+1,n)
if (a[i]>a[j]){
auto temp = myset.upper_bound(a[j]);
if (temp==myset.end()) {
dp[1][i][j] = 0;
continue;
}
dp[1][i][j] = (*temp);
}
myset.insert(a[i]);
}
rep1(i,1,n)
rep1(j,i+1,n)
if (a[i]>a[j]){
if (dp[0][i][j]==0 || dp[1][i][j]==0) continue;
if (dp[0][i][j]>a[j] && dp[1][i][j]<a[i] &&
dp[0][i][j]>dp[1][i][j]){
return true;
}
}
return false;
}
int main(){
#ifdef LOCAL_DEFINE
freopen("rush_in.txt", "r", stdin);
#endif
ios::sync_with_stdio(0),cin.tie(0);
int T;
cin >> T;
while (T--){
cin >> n;
rep1(i,1,n) cin >> a[i];
if (solve()){
cout<<"YES"<<endl;
continue;
}
reverse(a+1,a+1+n);
if (solve()){
cout<<"YES"<<endl;
continue;
}
cout<<"NO"<<endl;
}
return 0;
}
【習題 8-16 UVA - 1618】Weak Key