hdu4638 Group(離線線段樹)

Group

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1723    Accepted Submission(s): 904


Problem Description
There are n men ,every man has an ID(1..n).their ID is unique. Whose ID is i and i-1 are friends, Whose ID is i and i+1 are friends. These n men stand in line. Now we select an interval of men to make some group. K men in a group can create K*K value. The value of an interval is sum of these value of groups. The people of same group's id must be continuous. Now we chose an interval of men and want to know there should be how many groups so the value of interval is max.
 

Input
First line is T indicate the case number.
For each case first line is n, m(1<=n ,m<=100000) indicate there are n men and m query.
Then a line have n number indicate the ID of men from left to right.
Next m line each line has two number L,R(1<=L<=R<=n),mean we want to know the answer of [L,R].
 

Output
For every query output a number indicate there should be how many group so that the sum of value is max.
 

Sample Input
1 5 2 3 1 2 5 4 1 5 2 4
 

Sample Output
1 2
 

題意:n個人,序號爲1到n,將他們分儘可能少的組數,要求同組的人序號排序後是連續的。m次詢問,求問詢問的區間中的人至少可分成幾組。

先將所有詢問按右端點排序。將n個人依次存入線段樹,當第i個人、序號爲x的人加入線段樹時,將其認爲是獨立的一組,則第i個結點的sum值加1,若序號爲x - 1 或x + 1的人位置在他前面,則組數可以少1或2,則序號爲x - 1 或x + 1的人所在位置所對應的結點sum值減1。

此時,若詢問區間的右端點等於i,則答案爲區間內所有結點的sum值之和。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define ls node << 1
#define rs node << 1 | 1
#define lson l, mid, ls
#define rson mid + 1, r, rs
#define maxn 100005

using namespace std;

int n, m;
int sum[maxn << 2];

int a[maxn], p[maxn], ans[maxn];

struct B {
    int l;
    int r;
    int id;
} b[maxn];

bool cmp(B x, B y)
{
    return x.r < y.r;
}

void pushup(int l, int r, int node)
{
    sum[node] = sum[ls] + sum[rs];
}

void build(int l, int r, int node)
{
    if(l == r) {
        sum[node] = 0;
        return;
    }
    int mid = (l + r) >> 1;
    build(lson);
    build(rson);
}

void update(int x, int v, int l, int r, int node)
{
    if(l == x && r == x) {
        sum[node] += v;
        return;
    }
    int mid = (l + r) >> 1;
    if(x <= mid)
        update(x, v, lson);
    else
        update(x, v, rson);
    pushup(l, r, node);
}

int query(int x, int y, int l, int r, int node)
{
    if(l == x && r == y)
        return sum[node];
    int mid = (l + r) >> 1;
    if(x > mid)
        return query(x, y, rson);
    else if(y <= mid)
        return query(x, y, lson);
    else
        return query(x, mid, lson) + query(mid + 1, y, rson);
}

int main()
{
    int t,cnt;
    scanf("%d", &t);
    while(t--) {
        scanf("%d%d", &n, &m);
        build(1,n,1);
        for(int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
            p[a[i]] = i;
        }
        for(int i = 1; i <= m; i++) {
            scanf("%d%d", &b[i].l, &b[i].r);
            b[i].id = i;
        }
        sort(b + 1, b + m + 1, cmp);
        cnt = 1;
        for(int i = 1; i <= n; i++) {
            update(i, 1, 1, n, 1);
            //printf("*6*\n");
            //cout << a[i] << "   " << p[a[i] - 1] << endl;
            if(a[i] > 1 && p[a[i] - 1] < i)
                update(p[a[i] - 1], -1, 1, n, 1);
            //cout << a[i] << "   " << p[a[i] + 1] << endl;
            if(a[i] < n && p[a[i] + 1] < i)
                update(p[a[i] + 1], -1, 1, n, 1);
            //printf("*5*\n");
            while(cnt <= m && b[cnt].r == i) {
                ans[b[cnt].id] = query(b[cnt].l, b[cnt].r, 1, n, 1);
                cnt ++;
                //printf("*3*\n");
            }
        }
        //printf("*4*\n");
        for(int i = 1; i <= m; i++)
            printf("%d\n",ans[i]);
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章