http://acm.hdu.edu.cn/showproblem.php?pid=5172
判断一个区间是否为全排列是:
1、区间总和 = (1 + R - L + 1) * (R - L + 1) / 2;
2、区间没有重复数字
记录数组a[i]表示第i个数上一次在那个位置出现。
那么最需要在[L, R]中a[i]的最大值 >= L的,就是有重复数字了。
#include <bits/stdc++.h> #define IOS ios::sync_with_stdio(false) using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; #define root 1, n, 1 #define lson L, mid, cur << 1 #define rson mid + 1, R, cur << 1 | 1 int n, m; const int maxn = 10000000 + 2; LL sum[maxn]; int mx[maxn << 2]; int pre[maxn]; int a[maxn]; void pushUp(int cur) { mx[cur] = max(mx[cur << 1], mx[cur << 1 | 1]); } void build(int L, int R, int cur) { if (L == R) { mx[cur] = a[L]; return; } int mid = (L + R) >> 1; build(lson); build(rson); pushUp(cur); } int ask(int be, int en, int L, int R, int cur) { if (L >= be && R <= en) { return mx[cur]; } int mid = (L + R) >> 1; int ans = 0; if (be <= mid) ans = ask(be, en, lson); if (en > mid) ans = max(ans, ask(be, en, rson)); return ans; } void work() { for (int i = 1; i <= n; ++i) pre[i] = 0; for (int i = 1; i <= n; ++i) { int val; scanf("%d", &val); a[i] = pre[val]; pre[val] = i; sum[i] = sum[i - 1] + val; } build(root); for (int i = 1; i <= m; ++i) { int L, R; scanf("%d%d", &L, &R); LL t = (R - L + 2) * 1LL * (R - L + 1) / 2; if (t != sum[R] - sum[L - 1] || ask(L, R, root) >= L) { printf("NO "); continue; } printf("YES "); } } int main() { #ifdef local freopen("data.txt", "r", stdin); // freopen("data.txt", "w", stdout); #endif while (scanf("%d%d", &n, &m) > 0) work(); return 0; }