【树状数组】[COCI]Task HONI

树状数组首先按照a排个序,然后可以发现如果当前的这个大于前一个的那么把当前vector中的b全部加到树状数组里面,否则就把当前这个加进vector里面,如果i的两个都小于,那么i的排名最后一定小于当前的(这个树状数组搞就可以了),如果i的一个大于当前的,那么最后他的排名一定在当前的之前(不加),如果i的a或者b等于当前的非零的数字并且另一个等于0那么相差就刚好等于分数的最大值,那么最多就是和当前的平局,所以+1那么Mini=nQuery(bi1)如果ai==650那么还要减Sum1(bi)同理减去ai(只判断当前是650和有一个0的是因为两个的和最大相差650那么如果两个可能相等那么一定是一个相等另一个是相差650的,那么只需要判断这种情况就行了,其他的情况就是都可以大于当前的)的(这个Sum(i)表示的是当前一个为i的时候另一个为0的种类数量)那么最靠前的排名呢,很容易可以发现如果第i个ai, bi都大于当前的那么一定排名比当前的高(树状数组),否则的话最多相差一局的分数,所以最好的情况就是平局,那么我们答案Maxi=Query(bi)+1那么这道题目的复杂度就是O(nlog2n)

#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;
}

posted on 2015-09-07 14:03  JeremyGuo  阅读(209)  评论(0编辑  收藏  举报

导航