• 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;
    }
  • 相关阅读:
    freemarker报错之十一
    freemarker定义一个连续的序列
    freemarker报错之十
    freemarker之数组
    解决linux环境下nohup: redirecting stderr to stdout问题
    如何查看Linux操作系统版本?
    log file sync
    freemarker中的round、floor和ceiling数字的舍入处理
    freemarker中的split字符串分割
    freemarker中的left_pad和right_pad
  • 原文地址:https://www.cnblogs.com/BruceNoOne/p/3439399.html
Copyright © 2020-2023  润新知