POJ 2481 树状数组 区间覆盖(POJ2352 Stars 的变形题)(线段化点)

0)学会将题目情景转化为自己熟悉的结构或模型。

题目大意:

每个奶牛有自己的一个区间,求每个奶牛的区间所覆盖的子区间个数(注意,真子集,相等的不算),按照输入的顺序输出。

转化:

要学会将题目情景转化为自己熟悉的模型或结构上。把每个区间的左端x值作为点的x坐标,右端x值作为点的y坐标,就可以把所有区间转化为一个二维坐标图上的点集,而此时每个点左上方的点(同Stars那道题目一样不包括自身)的个数,就是每个区间所覆盖的子区间的个数(对应题目要求,这里或许可以再变形)。

同POJ2481 Stars:

不同的是,先线段化点,并对输入的数据进行预处理,即先按y从大到小,y相等的则按x从小到大,以保证,后用来更新树状数组的点不会在先被使用的点的左上方,每输入一个点,则输出该点左上方的点的个数,然后更新树状数组,再输入下一个点。

还记得01背包问题有二维数组转化为一维数组吗,有点相同的思想,这里只用x来做数组的下标,而y则从大到小输入,一边记录各个点的左上方点的个数,一边继续更新树状数组,而树状数组不再对之前的点有可查询性,只保证当前点的可查询性,比如出现这样的点集:(0,3)(1,2)(2,3),更新顺序是,先返回(0,3)左上方的点的个数,然后更新x>=0的所有点,返回(2,3)左上方的点的个数,然后更新x>=2所有的点,返回(1,2)左上方的点的个数,然后更新x>=1的所有的点,这时,x=2的点也会被+1,但因为(2,3)左上方的点已经被记忆到另一个数组或者输出,所以树状数组也不需要再对这个点的左上方有多少点保持记忆,而只是记录当前更新点(1,2)以及其他所有x>=1,y<=2的后面即将输入的点的左上方的当前点的个数。(所以让点按照y从大到小的顺序输入,以保证后用来更新树状数组的点不会在先被使用的点的左上方,所以用哪个点更新就可以确保此时返回的所用的当前点的左上方的点个数是正确的,是不会再增加的。)

1)

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>

using namespace std;
const int maxn=100010;
int n;
struct Qujian{
    int l;//该区间左端,每个区间化成一个点以后,左端值就是该点x值
    int r;//该区间右端,化点后,右端值就是该点y值
    int id;//输入次序
    //int v;
}qujian[maxn];
int stars[maxn];//相当于树状数组的c数组(树状数组的a数组a[x]中,x就是点的x坐标,每个点出现的次数就是a[x])
int value[maxn];//区间化为点后,对应id(输入次序)的点的左上方点的个数
bool cmp1(const Qujian a,const Qujian b){
    if(a.r>b.r)
        return 1;
    else if(a.r==b.r&&a.l<b.l){
        return 1;
    }
    else
        return 0;
}
bool cmp2(const Qujian a,const Qujian b){
    return a.id<b.id;
}
int Sum(int x){
    int res=0;
    while(x>0){
        res+=stars[x];
        x-=(x&(-x));
    }
    return res;
}
void Add(int x,int cou){
    while(x<=maxn){
        stars[x]+=cou;
        x+=(x&(-x));
    }
    return ;
}
int main()
{
    while(~scanf("%d",&n)&&n!=0){
        memset(qujian,0,sizeof(qujian));
        memset(stars,0,sizeof(stars));
        memset(value,0,sizeof(value));
        int l;
        int r;
        for(int i=0;i<n;i++){
            scanf("%d%d",&l,&r);
            qujian[i].id=i;
            qujian[i].l=l+1;
            qujian[i].r=r+1;//保证区间的位置从1开始而不会是0
        }
        sort(qujian,qujian+n,cmp1);//y从大到小,如果y相等则x从小到大,保证后出现的点不会在先出现的点的左上方,所以可以按这个顺序一边更新树状数组,一边求得各个点左上方有多少个点并记录下来
        int cou=1;//记录每个点出现的次数
        for(int i=0;i<n;i++){
            value[qujian[i].id]=Sum(qujian[i].l);//返回坐标为l的点的左上方点的个数(不包括自己),所以先返回再加自己的点进去
            if(i+1<n){
                if(qujian[i+1].l==qujian[i].l&&qujian[i+1].r==qujian[i].r){//注意,x,y,两个方向上的坐标都要保证相等,如果只看x坐标,那么就把y不同x相同的点误认为是同一个点了。
                    cou++;//碰到重复区间/相同点,则记录出现次数,等到最后一个进入并且返回其左上方个数之后,再一次性把这些点全部加入
                }
                else{
                    Add(qujian[i].l,cou);
                    cou=1;
                }
            }
            else if(i+1==n){
                Add(qujian[i].l,cou);
            }
        }
        //sort(qujian,qujian+n,cmp2);
        for(int i=0;i<n-1;i++){
            cout<<value[i]<<" ";
        }
        cout<<value[n-1]<<endl;
    }
    return 0;
}

2)

Description

Farmer John‘s cows have discovered that the clover growing along the ridge of the hill (which we can think of as a one-dimensional number line) in his field is particularly good.

Farmer John has N cows (we number the cows from 1 to N). Each of Farmer John‘s N cows has a range of clover that she particularly likes (these ranges might overlap). The ranges are defined by a closed interval [S,E].

But some cows are strong and some are weak. Given two cows: cow i and cow j, their favourite clover range is [Si, Ei] and [Sj, Ej]. If Si <= Sj and Ej <= Ei and Ei - Si > Ej - Sj, we say that cow i is stronger than cow j.

For each cow, how many cows are stronger than her? Farmer John needs your help!

Input

The input contains multiple test cases.

For each test case, the first line is an integer N (1 <= N <= 10 5), which is the number of cows. Then come N lines, the i-th of which contains two integers: S and E(0 <= S < E <= 10 5) specifying the start end location respectively of
a range preferred by some cow. Locations are given as distance from the start of the ridge.

The end of the input contains a single 0.

Output

For each test case, output one line containing n space-separated integers, the i-th of which specifying the number of cows that are stronger than cowi.

Sample Input

3
1 2
0 3
3 4
0

Sample Output

1 0 0

Hint

Huge input and output,scanf and printf is recommended.

时间: 2024-12-11 20:58:02

POJ 2481 树状数组 区间覆盖(POJ2352 Stars 的变形题)(线段化点)的相关文章

POJ 2481 Cows 简单树状数组区间覆盖

点击打开链接 Cows Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 13334   Accepted: 4413 Description Farmer John's cows have discovered that the clover growing along the ridge of the hill (which we can think of as a one-dimensional number line

poj 3067 poj 2481 树状数组变形+对区间排序

这种问题先对区间和线段进行排序,排序方法见代码cmp 然后分析其中一个点,用sum求值 poj 3067 Description Japan plans to welcome the ACM ICPC World Finals and a lot of roads must be built for the venue. Japan is tall island with N cities on the East coast and M cities on the West coast (M <

Cows(poj 2481 树状数组)

Cows Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 15301   Accepted: 5095 Description Farmer John's cows have discovered that the clover growing along the ridge of the hill (which we can think of as a one-dimensional number line) in hi

POJ 1195-Mobile phones(二维树状数组-区间更新区间查询)

Mobile phones Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 17661   Accepted: 8173 Description Suppose that the fourth generation mobile phone base stations in the Tampere area operate as follows. The area is divided into squares. The

POJ 3321 树状数组(+dfs+重新建树)

Apple Tree Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 27092   Accepted: 8033 Description There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow in the tree. Kaka likes apple very much, so he has been

hdu 1116 敌兵布阵(树状数组区间求最值)

题意: 给出一行数字,然后可以修改其中第i个数字,并且可以询问第i至第j个数字的和(i <= j). 输入: 首行输入一个t,表示共有t组数据. 接下来每行首行输入一个整数n,表示共有n个数字. 接下来每行首先输入一个字符串,如果是”Add”,接下来是两个整数a,b,表示给第i个数增加b.如果是”Query”,接下来是两个整数a,b,表示查询从第i个数到第j个数之间的和.如果是”End”,表示这组数据结束. 输出: 每组数据首先输出”Case X: ”,其中X表示第x组数. 每次查询,输出计算结

HRBUST 1161 树状数组区间更新求和

Leyni Time Limit: 3000 MS Memory Limit: 65536 K Total Submit: 267(64 users) Total Accepted: 82(57 users) Rating: Special Judge: No Description Leyni被人掳走,身在水深火热之中... 小奈叶为了拯救Leyni,独自一人前往森林深处从静竹手中夺回昏迷中的Leyni. 历经千辛万苦,小奈叶救出了Leyni,但是静竹为此极为恼怒,决定对他们发起最强烈的进攻.

hdu 1556:Color the ball(第二类树状数组 —— 区间更新,点求和)

Color the ball Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 8984    Accepted Submission(s): 4594 Problem Description N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的“小飞鸽"牌电动车从气球

hdu 1754 I Hate It(树状数组区间求最值)2007省赛集训队练习赛(6)_linle专场

题意: 输入一行数字,查询第i个数到第j个数之间的最大值.可以修改其中的某个数的值. 输入: 包含多组输入数据. 每组输入首行两个整数n,m.表示共有n个数,m次操作. 接下来一行包含n个整数. 接下来m行,每行包含一个字母s,两个整数a,b. 当s为’Q’,表示查询第a个数到第b个数之间的最大值. 当s为’U’,表示将第a个数更改为b. 输出: 每次查询输出一个结果,每次输出占一行. 题解: 点修改区间求最值,可以用树状数组模板. 具体见代码—— 1 #include <cstdio> 2