poj 2352 Stars

依旧感谢:http://blog.csdn.net/zxy_snow/代码几乎都是照着她的敲得。这里是她的新博客:http://www.xysay.com/

题意很简单:给定坐标点(整数),让你统计这个点的左下方有多少个点(行和列的值可以相同),一个坐标至多有一个点。由于数据是有序给出的,整体按行数递增给出,行数相同时列数递增。

解法:对于点(x,y),由于输入有序,只需要统计[0,x]这区间的最大值,然后对x点加1即可。选用线段树或者树状数组。

         我用的是线段树。维护一个左闭右开[0,MAXX+1),节点维护很好写。维护一个最大值即可(注意建树的时候节点要+1)。

  之前写线段树(其实也没几次)都是用的“点”树,准确说一个基本元素是一个点,根节点的l和r可以相等,现在改用了线段树,基本元素是长度为1的线段。

  每次更新节点,我之前的做法是,如果更新[x,y),当[x,y)不等于节点的l,r时,将x,y拆分,换而言之,就是拆分待操作区间去适应节点区间。每次写很繁琐。

  更好的做法是,当[x,y)不等于节点的l,r时,将l,r拆分,也就是用节点区间去适应待操作区间,更新、查询时只要x<=l,r<=y即可。

  对于左闭右开区间,拆分区间只要

    if(l<mid) update(L(f),l,r,value);
    if(r>mid) update(R(f),l,r,value);

对于l==mid或者r==mid的时候,我很是纠结了一段时间。其实对于左闭右开区间,如果l==mid,那么r一定>mid,反之亦然,上下两个必然只执行一个。

上代码:

query中注释掉的是我最开始的查询,拆分待操作区间去适应节点区间。

#include <iostream>
#include <cstdio>
#include <vector>
#include <cmath>
#include <algorithm>
#include <utility>
#include <cstring>
#include <fstream>
#include <string>

#define L(x) ( x << 1 )  
#define R(x) ( x << 1 | 1 )  
using namespace std;

const int MAXX=32004 ;//区间长度
const int MAXN=15004 ;
const int MARK=-65535;//标记,必要时可以有多个

struct tnode
{
    int mark,l,r;//mark=-65535 为未标记状态
    int mid(){    return (l+r)/2;}
    int len(){    return (r-l);}
    bool in(int ll,int rr) { return l >= ll && r <= rr; }
    int sum;
    //自行添加特殊数据:{lmax,rmax,max,num...}
} node[MAXX<<2];
int level[MAXN],n;
void build(int f,int l,int r)
{
    node[f].l=l;node[f].r=r;
    node[f].sum=node[f].mark=0;
    if(node[f].len()==1)
        return;
    int mid=node[f].mid();
    build(L(f),l,mid);
    build(R(f),mid,r);
}
void pushDown(int f)
{
    if(node[f].mark)
    {
        node[L(f)].mark+=node[f].mark;
            node[L(f)].sum+=node[f].mark;
        node[R(f)].mark+=node[f].mark;
            node[R(f)].sum+=node[f].mark;
        node[f].mark=0;
    }
}
void update(int f,int l,int r,int value)
{

    if(node[f].in(l,r))
    {
        node[f].sum+=value;
        node[f].mark+=value;
    }
    if(node[f].len()==1)
        return;
    pushDown(f);
    int mid=node[f].mid();
    if(l<mid) update(L(f),l,r,value);
    if(r>mid) update(R(f),l,r,value);
    node[f].sum=node[L(f)].sum+node[R(f)].sum;
    
}
int query(int f,int l,int r)
{

    /*if(node[f].l==l&&node[f].r==r)
        return node[f].sum;
    
        if(node[f].len()==1)
        return 0;
    
        pushDown(f);
        int mid=node[f].mid();
        if(r<=mid)
            return (query(L(f),l,r));
        else
        if(l>=mid)
            return query(R(f),l,r);
        else
            return query(L(f),l,mid)+query(R(f),mid,r);
    */
    if(node[f].in(l,r))
        return node[f].sum;
    pushDown(f);
    int ans = 0;  
    int mid = node[f].mid();
    if( l < mid ) ans += query(L(f),l,r);
    if( r > mid ) ans += query(R(f),l,r);  
    return ans;  
}

int main(int argc, char* argv[])
{
    while(scanf("%d",&n)!=EOF)
    {
        build(1,0,MAXX-2);
        memset(level,0,sizeof(level));
        int x,y,xx;
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&x,&y);
            int tmp=query(1,0,x+1);
            level[tmp]++;
            update(1,x,x+1,1);
        }
        for(int i=0;i<n;i++)
            printf("%d\n",level[i]);
    }
}

 

posted @ 2012-05-03 22:15  jzlikewei  阅读(193)  评论(0编辑  收藏  举报