Online JudgeProblem SetAuthorsOnline ContestsUser
Web Board
Home Page
F.A.Qs
Statistical Charts
Problems
Submit Problem
Online Status
Prob.ID:
Register
Update your info
Authors ranklist
Current Contest
Past Contests
Scheduled Contests
Award Contest
User ID:
Password:
  Register

解题思路以及个人写法:BIT or 线段树

Posted by 947186602 at 2020-09-15 10:26:15 on Problem 2352 and last updated at 2020-09-15 10:26:47
/**
天空上的星星有各自的等级,其等级为所有在它下面且它左边的星星数量和
现在按照y升序,x升序的顺序给你一群星星的坐标,
要你输出0到N-1等级的星星数量为多少? 1<=N<=15000 0<=X,Y<=32000
Sample Input
5
1 1
5 1
7 1
3 3
5 5
Sample Output
1
2
1
1
0

思路```
考虑输出新的(xi,yi)时,我们后面的输入的值肯定x或者y比当前值大,所以不用考虑计算
而之前输入的值一定满足处于下方(其y肯定不大于yi),那我们只需要考虑前面的点多少在左方,即在小于等于xi的有多少
如何快速判断小于等于xi有多少?------------
前缀和sum思想---BIT或者线段树,维护1~x,因为它们都需要避免x = 0的情况,而题目0<=X,Y<=32000,所以我们给所有的x+1
操作为区间查询,单点更新 BIT很香 线段树也行
空间够,无需离散化
**/

//BIT 140ms
#include<cstdio>
#include<string.h>
using namespace std;
const int MAX_N = 15005,MAX_X = 32005;
int num[MAX_N],N;
int BIT[MAX_X << 1];

int sum(int n){
     int res = 0;
     while(n > 0){
          res += BIT[n];
          n -= (n&-n);
     }
     return res;
}

void add(int n,int v){
     while(n <= MAX_X){
          BIT[n] += v;
          n += (n&-n);
     }
}

int solve_bit(int x,int y){
     int now = sum(x+1);
     add(x+1,1);
     return now;
}

int main(){
     while(~scanf("%d",&N)){
          int x,y;
          memset(num,0,sizeof(num));
          memset(num,0,sizeof(BIT));
          for(int i = 0;i < N;++i){
               scanf("%d%d",&x,&y);
               int sum = solve_bit(x,y);
               num[sum]++;
          }
          for(int i = 0;i < N;++i){
               printf("%d\n",num[i]);
          }
     }
     return 0;
}

-----------------------------------------------------------------
//线段树 188ms
#include<cstdio>
#include<string.h>
using namespace std;
const int MAX_N = 15005,MAX_X = 32005;
int num[MAX_N],N;
int tree[MAX_X << 2];

void update(int node,int L,int R,int pos,int v){
     if(L == R && L == pos){
          tree[node] += v;
          return;
     }
     int mid = L + R >> 1;
     if(pos <= mid)
          update(node << 1,L,mid,pos,v);
     if(pos > mid)
          update(node << 1 | 1,mid + 1,R,pos,v);
     tree[node] = tree[node << 1] + tree[node << 1 | 1];
}

int query(int node,int L,int R,int l,int r){
    if(l <= L && R <= r){
          return tree[node];
    }
    int res = 0;
    int mid = L + R >> 1;
    if(l <= mid){
          res += query(node << 1, L , mid,l,r);
    }
    if(r > mid){
          res += query(node << 1 | 1,mid+1,R,l,r);
    }
    return res;
}

int main(){
     while(~scanf("%d",&N)){
          int x,y;
          memset(tree,0,sizeof(tree));
          for(int i = 0;i < N;++i){
               scanf("%d%d",&x,&y);
               int r = query(1,1,MAX_X,1,x+1);
               num[r]++;
               update(1,1,MAX_X,x+1,1);
          }
          for(int i = 0;i < N;++i){
               printf("%d\n",num[i]);
          }
     }
     return 0;
}

Followed by:

Post your reply here:
User ID:
Password:
Title:

Content:

Home Page   Go Back  To top


All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator