トピックの主なアイデア:x座標とy座標のnペアが与えられた場合、さまざまなレベル[0、n-1]でポイントの数を見つけます。各ポイントのレベルは、ポイントの上下にあるポイントの数によって異なります。
アイデア:ツリーのような配列を使用して、さまざまな間隔で星の数を維持します。入力座標ペアをyに従って並べ替え、同じyをxに従って並べ替えます(昇順)。このように、ツリー配列を直接使用して、[1、x]の星の数を維持できます。これは、ツリー配列に毎回追加されるポイントのレベルが前のポイントのレベル以上である必要があるためです。。タイトルに記載されている座標は0である可能性があるため、x座標は+1として処理されます。
ANS配列を使用することの考え方:ANS配列を使用して、各レベルのポイント数を保存します。最初にツリー配列に追加したポイントiのレベルを取得し、次にレベルを添え字としてANS配列の要素をインクリメントします。次に、ツリー配列の間隔[1、x]内の星の数に1を追加します。更新します。
この質問では、ポイントのレベルにはそれ自体が含まれていないため、レベルと間隔の更新の順序に注意してください。最初にレベルを見つけてから、レベルを上げる必要があります。
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 15005;
int n, msum[maxn << 2], x, y, ANS[maxn];
struct Node{
int x, y;
}node[maxn];
bool cmp(Node a, Node b){
if(a.y == b.y) return a.x < b.x;
return a.y < b.y;
}
void update(int x, int v){
//要更新维护区间内的所有地方 ,因为,题目中给的x坐标并不知规定小于n。所以加lowbit 一直到maxn << 2.
for(int i = x; i <= maxn << 2;i += i & (-i)){
msum[i] += v;
}
}
int getNum(int x){
int ans = 0;
for(int i = x;i > 0; i -= i & (-i)){
ans += msum[i];
}
return ans;
}
int main(){
while(scanf("%d", &n) != EOF){
memset(ANS, 0, sizeof ANS);
memset(node, 0, sizeof node);
for(int i = 1;i <= n;i++){
scanf("%d%d", &node[i].x, &node[i].y);
node[i].x++;//该题需要防止下标为0;
}
sort(node + 1, node + n + 1, cmp);
//依次加入树状数组进行维护
for(int i = 1; i <= n;i++) {
ANS[getNum(node[i].x)]++;//等级为getNum(node[i].x)的星星数+1
update(node[i].x, 1);//更新维护区间,星星数加1
}
for(int i = 0;i < n;i++){
printf("%d\n",ANS[i]);
}
}
return 0;
}