hdu 5172 GTY's gay friends 線段樹 (未敲)

參考(轉自。):http://blog.csdn.net/u013654696/article/details/43636759GTY has n gay friends. To manage them conveniently, every morning he ordered all his gay friends to stand in a line. Every gay friend has a characteristic value ai , to express how manly or how girlish he is. You, as GTY’s assistant, have to answer GTY’s queries. In each of GTY’s queries, GTY will give you a range [l,r] . Because of GTY’s strange hobbies, he wants there is a permutation [1..r−l+1] in [l,r]
. You need to let him know if there is such a permutation or not.
Input
Multi test cases (about 3) . The first line contains two integers n and m ( 1≤n,m≤1000000 ), indicating the number of GTY’s gay friends and the number of GTY’s queries. the second line contains n numbers seperated by spaces. The ith number ai ( 1≤ai≤n ) indicates GTY’s ith gay friend’s characteristic value. The next m lines describe GTY’s queries. In each line there are two numbers l and r seperated by spaces ( 1≤l≤r≤n
), indicating the query range.
Output
For each query, if there is a permutation [1..r−l+1] in [l,r]
, print ‘YES’, else print ‘NO’.
Sample Input

8 5
2 1 3 4 5 2 3 1
1 3
1 1
2 2
4 8
1 5
3 2
1 1 1
1 1
1 2

Sample Output

YES
NO
YES
YES
YES
YES
NO

題意:

有n個元素的序列,和m個詢問, 每次詢問[l,r]的區間是不是1~r-l+1的一個排列。

思路:

對於一個長度爲len的區間, 如果最大值爲len,最小值爲1,並且區間元素沒有重複的話就說明它是一個1~len的排列, 最值可以用線段樹來求, 對於區間重複的話可以先預處理每個元素的下一個出現位置nxt[i], 如果區間裏面所有元素的下一個出現位置都大於r的話, 就表示這個區間沒有重複, 所以可以轉化成求nxt數組的區間最小值, 也可以用線段樹。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <stack>
#include <cmath>
#include <set>
#include <map>
#include <vector>
#include <queue>
#include <ctime>
#include <cstdlib>
using namespace std;

#define mxn 1000200
#define mxe 200020
#define mod 10000007
#define LL long long
#define inf 0x3f3f3f3f
#define vi vector<int>
#define PB push_back
#define MP make_pair
#define pii pair<int, int>
#define G(i, u) for(int i = fst[u]; ~i; i = nxt[i])
#define F(i, n) for(int i = 1; i <= n; ++i)
#pragma comment(linker,"/STACK:1024000000,1024000000")
#define ls (i << 1)
#define rs (ls | 1)
#define md ((ll + rr) >> 1)

int a[mxn], n, m;
int nxt[mxn], pre[mxn];
int mi[mxn << 2], mx[mxn << 2], s[mxn << 2];

void build(int ll, int rr, int i) {
    if(ll == rr) {
        mx[i] = mi[i] = a[ll];
        s[i] = nxt[ll];
        return;
    }
    build(ll, md, ls);
    build(md + 1, rr, rs);
    mx[i] = max(mx[ls], mx[rs]);
    mi[i] = min(mi[ls], mi[rs]);
    s[i] = min(s[ls], s[rs]);
}
int qm(int t, int l, int r, int ll, int rr, int i) {
    if(ll == l && rr == r) {
        if(t == 0)
            return mi[i];
        if(t == 1)
            return mx[i];
        return s[i];
    }
    if(r <= md) return qm(t, l, r, ll, md, ls);
    if(l > md) return qm(t, l, r, md + 1, rr, rs);
    if(t == 0)
        return min(qm(t, l, md, ll, md, ls), qm(t, md + 1, r, md + 1, rr, rs));
    if(t == 1)
        return max(qm(t, l, md, ll, md, ls), qm(t, md + 1, r, md + 1, rr, rs));
    if(t == 2)
        return min(qm(t, l, md, ll, md, ls), qm(t, md + 1, r, md + 1, rr, rs));
}
int main() {
    while(scanf("%d%d", &n, &m) != EOF) {
        for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
        memset(pre, -1, sizeof pre);
        for(int i = n; i >= 1; --i) {
            if(pre[a[i]] == -1) {
                nxt[i] = n + 1;
                pre[a[i]] = i;
            }
            else {
                nxt[i] = pre[a[i]];
                pre[a[i]] = i;
            }
        }
        build(1, n, 1);
        while(m--) {
            int l, r;
            scanf("%d%d", &l, &r);
            int len = r - l + 1;
            if(qm(0, l, r, 1, n, 1) == 1 && qm(1, l, r, 1, n, 1) == len && qm(2, l, r, 1, n, 1) > r)
                puts("YES");
            else
                puts("NO");
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章