/*
还是写下注释吧
这题是当树状数组的练习题做的
思想很简单:
先将每个点按横、纵坐标排序,再从左到右、从上到下遍历
对于不重合的每个点,计算当前点所能覆盖的点的个数
然后再进行add操作
就这样了
*/
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=33005;
struct point
{
int x,y;
bool operator < (const point& p1) const
{
if(p1.x!=x)
{
return x<p1.x;
}
else
return y<p1.y;
}
bool operator == (const point& p1) const
{
return (p1.x==x && p1.y==y);
}
};
int n,ma;
point s[maxn];
int a[maxn],ans[maxn];
int lowbit(int x)
{
return x&(-x);
}
void add(int x,int y)
{
while(x<=ma)
{
a[x]+=y;
x+=lowbit(x);
}
}
int sum(int x)
{
int ss=0;
while(x>0)
{
ss+=a[x];
x-=lowbit(x);
}
return ss;
}
int main()
{
cin>>n;
int i,j,k;
for(i=1;i<=n;i++)
{
cin>>s[i].x>>s[i].y;
ma=ma > s[i].y ? ma : s[i].y;
}
sort(s+1,s+n+1);
i=1;
while(i<=n)
{
int cnt=1;
while(s[i]==s[i+1])
{
cnt++;i++;
}
ans[sum(s[i].y)+cnt]+=cnt;
add(s[i].y,cnt);
i++;
}
for(i=1;i<=n;i++)
{
cout<<ans[i]<<endl;
}
return 0;
}
还是写下注释吧
这题是当树状数组的练习题做的
思想很简单:
先将每个点按横、纵坐标排序,再从左到右、从上到下遍历
对于不重合的每个点,计算当前点所能覆盖的点的个数
然后再进行add操作
就这样了
*/
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=33005;
struct point
{
int x,y;
bool operator < (const point& p1) const
{
if(p1.x!=x)
{
return x<p1.x;
}
else
return y<p1.y;
}
bool operator == (const point& p1) const
{
return (p1.x==x && p1.y==y);
}
};
int n,ma;
point s[maxn];
int a[maxn],ans[maxn];
int lowbit(int x)
{
return x&(-x);
}
void add(int x,int y)
{
while(x<=ma)
{
a[x]+=y;
x+=lowbit(x);
}
}
int sum(int x)
{
int ss=0;
while(x>0)
{
ss+=a[x];
x-=lowbit(x);
}
return ss;
}
int main()
{
cin>>n;
int i,j,k;
for(i=1;i<=n;i++)
{
cin>>s[i].x>>s[i].y;
ma=ma > s[i].y ? ma : s[i].y;
}
sort(s+1,s+n+1);
i=1;
while(i<=n)
{
int cnt=1;
while(s[i]==s[i+1])
{
cnt++;i++;
}
ans[sum(s[i].y)+cnt]+=cnt;
add(s[i].y,cnt);
i++;
}
for(i=1;i<=n;i++)
{
cout<<ans[i]<<endl;
}
return 0;
}