标签:main struct string eof str tree ret 长度 uil
给出一个序列,m个查询,每次查询区间是否是\([1, r - l + 1]\)的排列
判断是否是排列:
判断每个数字是否只出现一次,可以预处理每个数之和第一次出现这个数字的位置,如果没有那么设置为0,然后用线段树取查询区间最小值,如果是0或者比查询的右区间还打,那么这个区间里的数字只出现了一次。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#define ll long long
using namespace std;
const int N = 1e6 + 5;
int Next[N];
int a[N];
ll pre[N];
int n, m;
struct TREE{
int l, r, MA;
#define l(p) tree[p].l
#define r(p) tree[p].r
#define lson(p) p << 1
#define rson(p) p << 1 | 1
#define MA(p) tree[p].MA
} tree[N << 2];
void pushup(int p){
MA(p) = min(MA(lson(p)), MA(rson(p)));
}
void build(int p, int l, int r) {
l(p) = l, r(p) = r;
if(l == r) {
MA(p) = Next[l];
return;
}
int mid = (l + r) >> 1;
build(lson(p), l, mid);
build(rson(p), mid + 1, r);
pushup(p);
}
int query(int p, int l, int r){
if(l <= l(p) && r(p) <= r) {
return MA(p);
}
int mid = (l(p) + r(p)) >> 1;
int ans = n + 1;
if(l <= mid) ans = min(ans, query(lson(p), l, r));
if(r > mid) ans = min(ans, query(rson(p), l , r));
return ans;
}
int vis[N];
int main(){
while(scanf("%d%d", &n, &m) != EOF) {
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
pre[i] = pre[i - 1] + a[i];
Next[i] = i;
vis[a[i]] = 0;
}
for(int i = n; i >= 1; i--) {
if(vis[a[i]] != 0) Next[i] = vis[a[i]];
else Next[i] = n + 1;
vis[a[i]] = i;
}
build(1, 1, n);
for(int i = 1; i <= m; i++) {
int l, r;
scanf("%d%d", &l, &r);
ll now = pre[r] - pre[l - 1];
int num = (r - l + 1);
if(now == (1ll * num * (1 + num) / 2)){
int pos = query(1, l, r);
if(pos > r) printf("YES\n");
else printf("NO\n");
}else printf("NO\n");
}
}
return 0;
}
hdu5172 GTY's gay friends - 线段树查询区间数字是否只出现一次
标签:main struct string eof str tree ret 长度 uil
原文地址:https://www.cnblogs.com/Emcikem/p/13661841.html