Movie collection (树状数组)

本文介绍了一种使用树状数组解决电影堆栈查询问题的方法。该问题涉及维护一个动态变化的堆栈,实现快速查找特定电影在其堆栈中的相对位置,并在每次查询后将该电影移动到堆栈顶部。通过倒序插入和更新元素位置的方式,文章提供了一个高效的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Mr. K. I. has a very big movie collection. He has organized his collection in a big stack. Whenever he
wants to watch one of the movies, he locates the movie in this stack and removes it carefully, ensuring
that the stack doesn’t fall over. After he finishes watching the movie, he places it at the top of the
stack.
Since the stack of movies is so big, he needs to keep track of the position of each movie. It is
sufficient to know for each movie how many movies are placed above it, since, with this information,
its position in the stack can be calculated. Each movie is identified by a number printed on the movie
box.
Your task is to implement a program which will keep track of the position of each movie. In
particular, each time Mr. K. I. removes a movie box from the stack, your program should print the
number of movies that were placed above it before it was removed.
Input
On the first line a positive integer: the number of test cases, at most 100. After that per test case:
• one line with two integers n and m (1 ≤ n, m ≤ 100000): the number of movies in the stack and
the number of locate requests.
• one line with m integers a1, . . . , am (1 ≤ ai ≤ n) representing the identification numbers of movies
that Mr. K. I. wants to watch.
For simplicity, assume the initial stack contains the movies with identification numbers 1, 2, . . . , n
in increasing order, where the movie box with label 1 is the top-most box.
Output
Per test case:
• one line with m integers, where the i-th integer gives the number of movie boxes above the box
with label ai
, immediately before this box is removed from the stack.
Note that after each locate request ai
, the movie box with label ai
is placed at the top of the stack.
Sample Input
2
3 3
3 1 1
5 3
4 4 5
Sample Output
2 1 0
3 0 4

题目大概:

给出t个样例,每个有n个数叠起来放着(1在最上面),m条询问,每条询问,查看这个数的上面有多少个数,并且把这个数放在最上面。

思路:

一看题目的意思,感觉很有树状数组的性质,删除就是把这个点的位置赋值为-1,插入直接赋值为1。但是仔细思考一下,感觉不太好做,因为点是插在前面的。所以。我们可以把数倒着插入。这样最后的位置信息就是反的,需要用n减去算出来的数。

代码:

#include <bits/stdc++.h>

using namespace std;
//
const int maxn=1e5+10;
int c[maxn<<1];
int N,n;
int lowbit(int x)
{
    return x&(-x);
}
void add(int x,int v)
{
    while(x<=(maxn<<1)-5)
    {
        c[x]+=v;
        x+=lowbit(x);
    }

}
int sum(int x)
{
    int sum=0;
    while(x>0)
    {
        sum+=c[x];
        x-=lowbit(x);
    }
    return sum;
}
int b[maxn<<1],d[maxn<<1];
int main()
{
    int ans;
    int t;
    int m;
    scanf("%d",&t);
    while(t--)
    {
    scanf("%d%d",&N,&m);
    ans=0;
    n=N;
    memset(d,0,sizeof(d));
    memset(c,0,sizeof(c));
    int u;
    for(int i=1;i<=N;i++)  //倒着把数插入
    {
        b[i]=N-i+1;
        add(b[i],1);
    }
    for(int i=1;i<=m;i++)
    {
        scanf("%d",&u);
        d[ans++]=n-sum(b[u]);
        add(b[u],-1);  //删除
        b[u]=++N;
        add(b[u],1);  //插入
    }
    printf("%d",d[0]);
    for(int i=1;i<ans;i++)
    {
        printf(" %d",d[i]);
    }
    printf("\n");
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值