题意:
给出n个星星的坐标 x,y ,当存在其他星星的坐标x1,y1满足x>=x1&&y>=y1时 这个星星的等级就加1。
注意:
题中给的数据是有规律的 ,y是逐渐增加的 ,若y相等时x是逐渐增加的 。
思路:
~~怎么都没想到是线段树 ~~
因为当前给的坐标的yn 一定大于等于之前的y,那么只需要看之前有多少个小于xn 的坐标即可 (说白了就不用考虑y),这一步用线段树来实现:
对于每个xi 查询1到xi 的横坐标有多少个,那么怎么对x进行计数呢?对与每个xi 更新区间x->max(就是32000)进行加1操作 ,那么对于后面大于xi 的横坐标只需要单点查询它的xn 坐标 被加了多少次即可 ,即代码中的sum[o],就是i号星星的等级
上代码:
//A code block
#include<iostream>
#include<stdio.h>
using namespace std;
int n,m,lazy[150005],sum[150005];/*区间最大值 不断加1*/
void pushdown(int l,int r,int o)
{
if(lazy[o])
{
lazy[o<<1|1]+=lazy[o];
lazy[o<<1]+=lazy[o];
sum[o<<1|1]+=lazy[o];
sum[o<<1]+=lazy[o];
lazy[o]=0;
}
}
void update(int x,int y,int l,int r,int o)
{
if(x<=l&&y>=r)
{
sum[o]++;
lazy[o]++;
return ;
}
pushdown(l,r,o);
int mid=(l+r)>>1;
if(x<=mid) update(x,y,l,mid,o<<1);
if(y>mid) update(x,y,mid+1,r,o<<1|1);
sum[o]=max(sum[o<<1],sum[o<<1|1]);
return ;
}
int k=0;
void query(int x,int y,int l,int r,int o)
{
if(x<=l&&y>=r)
{
k=max(sum[o],k);
return ;
}
pushdown(l,r,o);
int mid=(l+r)>>1;
if(x<=mid) query(x,y,l,mid,o<<1);
if(y>mid) query(x,y,mid+1,r,o<<1|1);
return ;
}
int main()
{
while(~scanf("%d",&m))
{
int x,y,grade[15010],maxx=32005;
for(int i=0;i<=15000;i++)
grade[i]=0;
for(int i=0;i<=150000;i++)
lazy[i]=sum[i]=0;
for(int i=1;i<=m;i++)
{
k=0;
scanf("%d%d",&x,&y);
x++,y++;
query(1,x,1,maxx,1);
grade[k]++;
update(x,maxx,1,maxx,1);
}
for(int i=0;i<m;i++)
printf("%d\n",grade[i]);
}
return 0;
}
var foo = 'bar';