HDU 5172 GTY's gay friends 线段树+前缀和+全排列

题目链接:

hdu: http://acm.hdu.edu.cn/showproblem.php?pid=5172

bc(中文): http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=567&pid=1003

题解:

线段树+前缀和

一个区间要满足1到n的一个排列,要同时满足两点,一是它的和是n*(n+1)/2,这个可以用前缀和直接求;二是它每个元素不能重复。

区间内每个元素都不能重复:

  记录第i个元素的左边一个离他最近的值与他相等的数的位置,记在arr[i]里面,对于区间[L,r]要满足区间里面最大的arr[i](L<=i<=r)要小于L;这个可以用线段树或rmq维护。

要先比较第一个条件,即和要先等于n*(n+1)/2,满足了再去查线段树,否则会超时。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define lson (o<<1)
 6 #define rson ((o<<1)+1)
 7 #define M (l+(r-l)/2)
 8 using namespace std;
 9 typedef long long LL;
10 
11 const int maxn = 1e6 + 10;
12 LL sumv[maxn << 2];
13 int maxv[maxn << 2];
14 int arr[maxn],vis[maxn];
15 int n, m;
16 
17 int max(int a, int b) { return a > b ? a : b; }
18 
19 void build(int o, int l, int r) {
20     if (l == r) {
21         maxv[o] = arr[l];
22     }
23     else {
24         build(lson, l, M);
25         build(rson, M + 1, r);
26         maxv[o] = max(maxv[lson], maxv[rson]);
27     }
28 }
29 
30 int ql, qr;
31 void query(int o, int l, int r,int &ma) {
32     if (ql <= l&&r <= qr) {
33         ma = max(ma, maxv[o]);
34     }
35     else {
36         if (ql <= M) query(lson, l, M,ma);
37         if (qr > M) query(rson, M + 1, r, ma);
38     }
39 }
40 
41 bool check(int l,int r) {
42     LL nn = r - l + 1;
43     if (nn*(nn + 1) / 2 != sumv[r] - sumv[l - 1]) return false;
44     int ma = -1;
45     query(1, 1, n,ma); 
46     if (ma >= l) return false;
47     return true;
48 }
49 
50 void init() {
51     sumv[0] = 0;
52     memset(vis, 0, sizeof(vis));
53 }
54 
55 int main() {
56     while(scanf("%d%d", &n, &m) == 2 && n) {
57         init();
58         for (int i = 1; i <= n; i++) {
59             int x;
60             scanf("%d", &x);
61             sumv[i] = sumv[i - 1] + x;
62             arr[i] = vis[x];
63             vis[x] = i;
64         }
65         build(1,1,n);
66         while (m--) {
67             scanf("%d%d", &ql, &qr);
68             LL len = qr - ql + 1;
69             if (check(ql,qr)) {
70                 puts("YES");
71             }
72             else {
73                 puts("NO");
74             }
75         }
76     }
77     return 0;
78 }

 

posted @ 2016-04-28 01:09  fenicnn  阅读(264)  评论(0编辑  收藏  举报