HDU 5172
超内存了,呃。。。不知道如何优化了。
首先要判断区间的和是否和1~n的和相等。
再个,记录下每个数字前一次出现的位置,求这些位置的最大值,如果小于左端点,则表示有这样的一个序列。
呃~~~第二个条件当时曾有想过,但认为要在O(1)时间内得出不可能,后来才知道,还有ST算法啊。。。。不让熟练啊。。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define LL __int64
using namespace std;
const int MAX=1000002;
int num[MAX],pre[MAX];
double sum[MAX];
int dp[MAX][21];
void ST(int n){
int i, j, k, m;
k = (int) (log((double)n) / log(2.0));
for(i = 1; i <= n; i++) {
dp[i][0] = num[i];
}
for(j = 1; j <= k; j++) {
for(i = 1; i + (1 << j) - 1 <= n; i++) {
m = i + (1 << (j - 1));
dp[i][j] = max(dp[i][j-1], dp[m][j-1]);
}
}
}
int rmq(int i, int j) {
int k = (int)(log(double(j-i+1)) / log(2.0)), t1;
t1 =max(dp[i][k], dp[j - (1<<k) + 1][k]);
return t1;
}
int main(){
int n,m,tmp,l,r,i; double tsum;
while(scanf("%d%d",&n,&m)!=EOF){
sum[0]=0;
memset(pre,0,sizeof(pre));
for(i=1;i<=n;i++){
scanf("%d",&tmp);
sum[i]=sum[i-1]+tmp;
num[i]=pre[tmp];
pre[tmp]=i;
}
ST(n);
while(m--){
scanf("%d%d",&l,&r);
tsum=(r-l+2)*(r-l+1)*1.0/2.0;
if(tsum!=sum[r]-sum[l-1]){
puts("NO");
continue;
}
if(rmq(l,r)<l){
puts("YES");
}
else puts("NO");
}
}
return 0;
}

浙公网安备 33010602011771号