【树状数组】[COCI]Task HONI
树状数组首先按照a排个序,然后可以发现如果当前的这个大于前一个的那么把当前vector中的b全部加到树状数组里面,否则就把当前这个加进vector里面,如果i的两个都小于,那么i的排名最后一定小于当前的(这个树状数组搞就可以了),如果i的一个大于当前的,那么最后他的排名一定在当前的之前(不加),如果i的a或者b等于当前的非零的数字并且另一个等于0那么相差就刚好等于分数的最大值,那么最多就是和当前的平局,所以+1那么
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
const int MAXS = 670;
const int MAXN = 50000;
struct node{
int id, a, b;
node(){}
node(int i, int _a, int _b){
a=_a; b=_b; id=i;
}
}vec[MAXN*2+10];
int Tree[MAXS+10], Min[MAXN+10], Max[MAXN+10]; vector<node> Tmp;
int Sum1[MAXS+10], Sum2[MAXS+10];
int _bit(int u){return (u&(-u));}
void Add(int u){
while(u<=MAXS){
Tree[u]++;
u += _bit(u);
}
}
int Query(int u){
int ret = 0;
while(u > 0){
ret += Tree[u];
u -= _bit(u);
}
return ret;
}
bool cmp(node a, node b){return a.a < b.a;}
int main(){
int n, a, b;
scanf("%d", &n);
for(int i=1;i<=n;i++){
scanf("%d%d", &a, &b);
a+=2; b+=2;
vec[i] = node(i, a, b);
if(a == 2) Sum1[b]++;
if(b == 2) Sum2[a]++;
}
sort(vec+1, vec+1+n, cmp);
Tmp.clear();
memset(Tree, 0, sizeof Tree);
for(int i=1;i<=n;i++){
if(vec[i].a != vec[i-1].a){
int sz = Tmp.size();
for(int j=0;j<sz;j++)
Add(Tmp[j].b);
Tmp.clear();
}
Min[vec[i].id] = n-Query(vec[i].b-1);
if(vec[i].a == 652) Min[vec[i].id] -= Sum1[vec[i].b];
if(vec[i].b == 652) Min[vec[i].id] -= Sum2[vec[i].a];
Tmp.push_back(vec[i]);
}
Tmp.clear();
memset(Tree, 0, sizeof Tree);
for(int i=n;i>0;i--){
if(vec[i].a != vec[i+1].a){
int sz = Tmp.size();
for(int j=0;j<sz;j++)
Add(MAXS-Tmp[j].b);
Tmp.clear();
}
Max[vec[i].id] = Query(MAXS-vec[i].b-1)+1;
Tmp.push_back(vec[i]);
}
for(int i=1;i<=n;i++)
printf("%d %d\n", Max[i], Min[i]);
return 0;
}