[POJ 2481] Cows 线段树

来源:互联网 发布:樱井知香在哪里可以看 编辑:程序博客网 时间:2024/04/29 16:58

http://poj.org/problem?id=2481

题意:这里就是求区间覆盖问题,求每个区间被多少区间覆盖,相同两个区间的不算。

思路:线段数,先将所有区间 [l, r] 按照 r 位置降序排列,然后将线段树中 l 位置的 sum + 1,插入后统计[0, l] 区间的和。

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;/const int maxn = 100005;struct node{    int id, l, r, sum;    friend bool operator < (node a, node b){        return a.r > b.r || (a.r == b.r && a.l < b.l);    }};int n;int sta[maxn];node mapn[maxn];node tr[maxn<<2];int Build(int rt, int l, int r) //构建线段树{    tr[rt].l = l;    tr[rt].r = r;    tr[rt].sum = 0;    if(l == r)        return 0;    int mid = (l + r) >> 1;    Build(rt<<1, l, mid);    Build(rt<<1|1, mid + 1, r);    return 0;}int Insert(int rt, int x, int val)  //将 x 位置的 sum 加上val{    if(tr[rt].l > x || tr[rt].r < x)        return tr[rt].sum;    if(tr[rt].l == tr[rt].r){        tr[rt].sum += val;        return tr[rt].sum;    }    tr[rt].sum = Insert(rt<<1, x, val) + Insert(rt<<1|1, x, val);    return tr[rt].sum;}int query(int rt, int l, int r)  //查询{    if(tr[rt].l > r || tr[rt].r < l)        return 0;    if(tr[rt].l >= l && tr[rt].r <= r)        return tr[rt].sum;    return query(rt<<1, l, r) + query(rt<<1|1, l, r);}int main(){    while(scanf("%d", &n) && n){    int len = -1;        for(int i = 0; i < n; i++){            mapn[i].id = i;            scanf("%d%d", &mapn[i].l, &mapn[i].r);            if(mapn[i].r > len)                len = mapn[i].r;        }        sort(mapn, mapn+n);        Build(1, 0, len);        int sum = 1;        for(int i = 0; i < n; i++){            sta[mapn[i].id] = query(1, 0, mapn[i].l); //先查询            if(mapn[i].l == mapn[i+1].l && mapn[i].r == mapn[i+1].r){                sum++;                continue;  //避免将相同的计算进去,所以先不插入            }            Insert(1, mapn[i].l, sum);  //最后一个插入,避免重复            sum = 1;        }        for(int i = 0; i < n; i++){            printf("%d ",sta[i]);        }        printf("\n");    }    return 0;}
0 0
原创粉丝点击