hdu4638 Group(离线线段树)

来源:互联网 发布:织梦dedecms 编辑:程序博客网 时间:2024/05/22 18:24

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
15 23 1 2 5 41 52 4
 

Sample Output
12
 

题意: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 100005using 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]);    }}


0 0
原创粉丝点击