poj2481 线段树(单点更新)

题意:有N条牛它们有一个自己的区间[s,e];题目输出的是有多少条牛能胜过自己,胜过的意思是如果牛j的区间能完全覆盖牛i的区间即为胜过。

思路:这个可以转换到数轴上理解了,下图就为cow[j]胜过cow[i];

所以只需先对左端点从小到大,右端点从大到小排序;再查询从右端点到最大值之间有多少个就是答案了,需要注意的是如果区间重合就不需要重复算。

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 200009
#define lson left,mid,rt<<1
#define rson mid+1,right,rt<<1 | 1

int sum[maxn << 2];
int Count[maxn];
struct node
{
    int i, st, et;
    void input(int s, int e, int ii)
    {
        i = ii;
        st = s;
        et = e;
    }
    bool operator < (const node &b)const
    {
        return st < b.st || (st == b.st && et > b.et);
    }
} cow[maxn];

void push_up(int rt)
{
    sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
}
void build(int left, int right, int rt)
{
    sum[rt] = 0;
    if(left == right)
        return ;
    int mid = (left + right) >> 1;
    build(lson);
    build(rson);
}
void updata(int p, int left, int right, int rt)
{

    if(left == right)
    {
        sum[rt]++;
        return ;
    }
    int mid = (left + right) >> 1;
    if(p <= mid) updata(p, lson);
    else  updata(p, rson);
    push_up(rt);
}
int query(int L, int R, int left, int right, int rt)
{
    if(L <= left && R >= right)
        return sum[rt];
    int ret = 0;
    int mid = (left + right) >> 1;
    if(L <= mid) ret += query(L, R, lson);
    if(R > mid) ret += query(L, R, rson);
    return ret;
}

int main()
{
    int n, i;
    while(scanf("%d", &n), n)
    {
        int s, e;
        memset(Count, 0, sizeof(Count));
        for(i = 0; i < n; i++)
        {
            scanf("%d%d", &s, &e);
            cow[i].input(s, e, i);
        }
        build(1, n, 1);
        sort(cow, cow + n);
        for(i = 0; i < n; i++)
        {
            if(i && cow[i].st == cow[i - 1].st && cow[i].et == cow[i - 1].et)
                Count[cow[i].i] = Count[cow[i - 1].i];
            else
                Count[cow[i].i] = query(cow[i].et, n, 1, n, 1);
            updata(cow[i].et, 1, n, 1);
        }
        printf("%d", Count[0]);
        for(i = 1; i < n; i++)
            printf(" %d", Count[i]);
        printf("
");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/BruceNoOne/p/3439399.html