本文共 1571 字,大约阅读时间需要 5 分钟。
题目链接:
给你一个n个数的数组,m次询问,询问在[L, R] 这个区间里面有没有 [1, R-L+1] 的数。
判断有没有 1 ~ R-L+1 其实就是判断这一段区间和是不是等于 (R-L+1)*(R-L+1+1)/ 2 。
当然还有就是每一个数只能出现1次。
这个问题我们应该怎么解决呢。
我们可以记录第i个数x 的前一个x出现的位置。如果x的前一个x也出现在[L, R]里面,那么这一段区间就不是1~R-L+1 的全排列。
所以我们可以O(n) 处理位置为i 的数x 的前一个数的位置 pre[i] 。
用线段树维护这个pre[i] 的区间最大值。在[L, R] 这个区间的pre[i] 的最大值如果在[L, R] , 就NO。
1 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 #include 10 #include 11 #include 12 using namespace std;13 typedef long long LL;14 typedef unsigned long long uLL;15 #define ms(a, b) memset(a, b, sizeof(a))16 #define rep(a, b) for(int a = 0;a >1;33 int ans = -1;34 if(ql <= L && R <= qr) return maxv[o];35 if(ql <= M) ans = max(ans, query(ql, qr, o*2, L, M));36 if(M < qr) ans = max(ans, query(ql, qr, o*2+1, M+1, R));37 return ans;38 }39 void update(int o, int L, int R)40 {41 if(L==R){42 maxv[o] = pre[L];43 return;44 }45 int M = (L+R)>>1;46 update(o*2, L, M);47 update(o*2+1, M+1, R);48 maxv[o] = max(maxv[o*2], maxv[o*2+1]);49 }50 void solve()51 {52 ms(now, 0);sum[0] = 0;53 for(int i = 1;i<=n;i++){54 scanf("%d", &x);55 sum[i] = sum[i-1] + 1LL*x;56 pre[i] = now[x];57 now[x] = i;58 }59 update(1,1,n);60 while(m--){61 scanf("%d%d",&l, &r);62 LL len = 1LL*(r-l+1);63 if(sum[r]-sum[l-1] != len*(len+1)/2){64 printf("NO\n");continue;65 }66 int Max = query(l, r, 1, 1, n);67 if(Max
转载于:https://www.cnblogs.com/denghaiquan/p/7266015.html