Lightoj1187 Lining up Students(树状数组)

题意
有n个人,每个人有不同的身高,n个人站成一条线,每个人说出左边比自己高的人数,问最左边的人是第几高的。
思路
可以从最右边开始做,比如n = 10, a[n]=2,说明左边比他高的有5人,那么b[n] = 8;a[n-1] = 4,说明左边比他高的有4人,
b[n-1] = 5,因为8出现在了他的右边,不能算在里面,这样就显然是二分+树状数组,因为线断树TLE了。
/*****************************************
Author      :Crazy_AC(JamesQi)
Time        :2016
File Name   :
*****************************************/
// #pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <sstream>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <vector>
#include <map>
#include <set>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <climits>
using namespace std;
#define MEM(x,y) memset(x, y,sizeof x)
#define pk push_back
#define lson rt << 1
#define rson rt << 1 | 1
#define bug cout << "BUG HERE\n"
#define ALL(v) (v).begin(), (v).end()
#define lowbit(x) ((x)&(-x))
#define showtime printf("time = %.15f\n",clock() / (double)CLOCKS_PER_SEC)
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> ii;
typedef pair<ii,int> iii;
const double eps = 1e-8;
const double pi = 4 * atan(1);
const int inf = 1 << 30;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
int nCase = 0;
int dcmp(double x){//精度正负、0的判断
    if (fabs(x) < eps) return 0;
    return x < 0?-1:1;
}
template<class T>
inline bool read(T &n)
{
    T x = 0, tmp = 1;
    char c = getchar();
    while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();
    if(c == EOF) return false;
    if(c == '-') c = getchar(), tmp = -1;
    while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();
    n = x*tmp;
    return true;
}
template <class T>
inline void write(T n)
{
    if(n < 0)
    {
        putchar('-');
        n = -n;
    }
    int len = 0,data[20];
    while(n)
    {
        data[len++] = n%10;
        n /= 10;
    }
    if(!len) data[len++] = 0;
    while(len--) putchar(data[len]+48);
}
const int maxn = 1e5 + 100;
// struct SegmentTree {
//     struct node {int l, r, sum;}p[maxn<<2];
//     void build(int rt,int L, int R) {
//         p[rt] = node{L, R, 1};
//         if (L == R) return ;
//         int mid = (L + R) >> 1;
//         build(lson, L, mid), build(rson, mid + 1, R);
//         p[rt].sum = p[lson].sum + p[rson].sum;
//     }
//     void updata(int rt,int pos, int val) {
//         if (p[rt].l == pos && p[rt].r == pos) {
//             p[rt].sum = val;
//             return ;
//         }
//         int mid = (p[rt].l + p[rt].r) >> 1;
//         if (pos <= mid) updata(lson, pos, val);
//         if (pos > mid) updata(rson, pos, val);
//         p[rt].sum = p[lson].sum + p[rson].sum;
//     }
//     int Query(int rt,int L, int R) {
//         if (L <= p[rt].l && p[rt].r <= R) return p[rt].sum;
//         int res = 0;
//         int mid = (p[rt].l + p[rt].r) >> 1;
//         if (L <= mid) res += Query(lson, L, R);
//         if (R > mid) res += Query(rson, L, R);
//         return res;
//     }
// }solve;


struct BIT {
    int a[maxn];
    int n;
    void add(int p,int val) {
        while(p <= n) {
            a[p] += val;
            p += lowbit(p);
        }
    }
    void init(int n) {
        this->n = n;
        memset(a, 0, sizeof a);
        for (int i = 1;i <= n;++i) 
            add(i, 1);
    }
    int sum(int p) {
        int res = 0;
        while(p > 0) {
            res += a[p];
            p -= lowbit(p);
        }
        return res;
    }
}solve;


int a[maxn];
int b[maxn];
int main(int argc, const char * argv[])
{    
    // freopen("in.txt","r",stdin);
    // freopen("out.txt","w",stdout);

    int kase;cin >> kase;
    while(kase--) {
        int n;scanf("%d", &n);
        for (int i = 1;i <= n;++i)
            scanf("%d", &a[i]);
        // solve.build(1, 1, n);
        solve.init(n);
        for (int i = n;i >= 1;--i) {
            int r = n, l = 1;
            int p = 0;
            while(l <= r) {
                int mid = (l + r) >> 1;
                int res = i - solve.sum(mid);
                // printf("[l = %d, r = %d, res = %d, mid = %d]\n", l, r, res, mid);
                if (res <= a[i]) {
                    if (res == a[i]) p = mid;
                    r = mid - 1;
                }else l = mid + 1;
                // printf("[res = %d]\n", res);
            }
            // printf("[p = %d]\n", p);
            b[i] = p;
            solve.add(p, -1);
        }
        printf("Case %d: %d\n", ++nCase, b[1]);
    }

    // showtime;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值