uva 1513

#include <cstdio>
#include <iostream>
#include <cstring>
#include <map>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#include <set>
#include <queue>
#include <vector>
#include <stack>

using namespace std;

const int maxn = 1e5 + 5;

int c[2 * maxn];//树状数组
int pos[maxn];//原始数组
int n, m;

int lowbit(int x)//求某个点的管辖范围
{
    return (x&(-x));//加上求得管辖x的点,减去求得x管辖的点
}

void add (int p, int v)//修改树状数组
{
    while (p < 2 * maxn)
    {
        c[p] += v;//p加一,所有管辖p的点都要加一
        p += lowbit(p);//这句不断找到所有管辖p的点
    }
}

int sum (int p)//sum(x)就是求前x项的和
{
    int ret = 0;//求和
    while (p > 0)
    {
        ret += c[p];
        p -= lowbit(p);//求得x管辖的点
    }
    return ret;
}

int main ()
{
    int T;
    scanf ("%d", &T);
    while (T--)
    {
        memset (c, 0, sizeof (c));
        scanf ("%d%d", &n, &m);
        for (int i = 1; i <= n; i++)
        {
            pos[i] = n - i + 1;//因为建树要从根节点开始,树的位置和原始位置是反着的,比如n=16时,i=16,它在树状数组是根,所以位置是1。
            add(pos[i], 1);//依据原始数组构建树状数组
        }
        int num;
        int N = n;
        for (int i = 1; i <= m; i++)
        {
            scanf ("%d", &num);
            printf ("%d%c", n - sum(pos[num]), i == m ? '\n':' ');
            //举例说下位置问题:还是假设n=16,num=7时按照题意应该求7上面有多少部电影,用sum求的是树状数组1-10的和,相当于
            //原始数组的7-16的和,所以在用n减去就是目标值,和上面的位置储存正好对应
            add(pos[num], -1);//修改树状数组,拿出这部电影
            pos[num] = ++N;//num处理完后位置改变,N最大为2*n,所以c这个树状数组要开2*maxn
            add(pos[num], 1);//修改树状数组,添加树的叶,把这部电影放到最上面
        }
    }
    return 0;
}
初学者结合着这个博客看看很快就能理解树状数组了

http://www.cnblogs.com/Penn000/articles/5758324.html


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值