BNUOJ-22868-Movie collection(树状数组)

Description

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(1nm100000): the number of movies in the stack and the number of locate requests.
  • one line with m integers a1,..., am(1ain) 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题意:有n部电影,询问m次,询问第i部电影前面有多少部电影。每次询问把询问的电影放到栈的顶部,以第一组为例:询问3,3前面有1和2两部电影,就输出2;询问1,因为3调到第一位了,1前面就有1部电影,就输出1;询问1,1已经调到第一位了1前面没有电影,就输出0.思路:树状数组;具体:先把树状数组有的电影下标标为1,因为树状数组下标不能小于1,录入时应该从n+1开始(代码中n,m和题目中相反,以代码为准),每次录入把树状数组更新。ac代码
 1 #include<stdio.h>
 2 #include<string.h>
 3 int  m,n,d1[2000000],t[2000000];
 4 int lowbit(int x)
 5 {
 6     return x&(-x);
 7 }
 8 int sum(int x)
 9 {
10     int res=0;
11     while(x>0)
12     {
13         res+=d1[x];
14         x-=lowbit(x);
15     }
16     return res;
17 }
18 void add(int x,int d)
19 {
20     while(x<=n+m)
21     {
22         d1[x]+=d;
23         x+=lowbit(x);
24     }
25 }
26 int main()
27 {
28     int a,b,i,j;
29     scanf("%d",&a);
30     while(a--)
31     {
32         memset(d1,0,sizeof(d1));
33         memset(t,0,sizeof(t));
34         scanf("%d%d",&m,&n);
35         for(i=1+n; i<=m+n; i++)
36         {
37             add(i,1);
38             t[i-n]=i;
39         }
40         int min=n+1;
41         for(i=1; i<=n; i++)
42         {
43             scanf("%d",&b);
44             if(i==1)
45             printf("%d",sum(t[b]-1));
46             else
47             printf(" %d",sum(t[b]-1));
48             add(t[b],-1);
49             min--;
50             t[b]=min;
51             add(min,1);
52         }
53         printf("\n");
54     }
55 }
 

BNUOJ-22868-Movie collection(树状数组)

时间: 2024-08-01 16:58:23

BNUOJ-22868-Movie collection(树状数组)的相关文章

UVa 1513 Movie collection (树状数组)

题意:给定给你一叠DV,编号1到n,1在最上面,n在最下面.然后现在给你m个操作,每次都指定一张CD,问要拿走这个CD需要挪走上面多少张CD,并且这个要拿走的CD放在这个叠CD的顶端. 析:这个题要倒着来做,我就是正着做的,太复杂了,因为每次操作后,都要再重新处理后面的数,时间复杂度太高. 如果是倒着做,每次只要更新后面的就好,不用管前面的数,因为前面的是不会影响到的. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000&quo

LA 5902 Movie collection (树状数组)

题目:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=27885 题意:有n个物品从上到下放置,并且标号1~n,有n次查询,每次查询标号为x的物品现在的位置(0~n,即该物品上面有多少个物品),同时将该物品取出放到第0号位置. 分析:将1~n件物品重新编号,1~n标为n~1,每次拿出一件物品x,再将其重新编号,如果是第一次拿出就标为n+1.....依次递增,然后将之前的编号删掉,插入新的编号. 代码: #include <c

Uva - 1513 Moive collection ( 模拟栈 + 树状数组基本操作 )

Uva - 1513 Moive collection ( 模拟栈 + 树状数组基本操作 ) 题意: 一个书架,原来所有的书都是按顺序摆好的,书的编号从1开始到n 操作: 取出一本书,统计在这本书之前有多少本书,统计完之后,将这本书放在书架的第一位. 如:  1 2 3 4 5取4   4 1 2 3 5 (取之前,有3本书在4前面,取完后,将4放在栈顶)取4   4 1 2 3 5 (取之前,有0本书在4前面,取完后,将4放在栈顶)取2   2 4 1 3 5 (取之前,有2本书在2前面,取完

UVA 1513 Movie collection (树状数组+反向存储)

题意:给你n盘歌碟按照(1....n)从上到下放,接着m个询问,每一次拿出x碟,输出x上方有多少碟并将此碟放到开头 直接想其实就是一线段的区间更新,单点求值,但是根据题意我们可以这样想 首先我们倒着存  n--1,接着每次询问时把放碟子放到最后,这样我们要开一个映射数组映射每个碟子在哪个位置 其中我们需要使用树状数组维护每个绝对位置是否有碟子(有些碟子已经放到了后面了),再使用区间求和就好了 #include<set> #include<map> #include<queue

【DFS序+树状数组】BNUOJ 52733 Random Numbers

http://acm.bnu.edu.cn/v3/problem_show.php?pid=52733 [题意] 给定一棵树,这棵树每个点都有一个点权,标号从0开始,0是根结点 修改操作: SEED 1 13 把结点1的点权乘上13 查询操作: RAND 1 查询结点1为根的子树所有结点权的总乘积,以及这个总乘积有多少个因子 题目保证结果的质因子最大为13 [思路] 质因子最大为13,那么我们可以枚举质因子2 3 5 7 11 13,共6个 只要我们知道子树乘积这六个质因子的个数,我们就能算出子

UVA 1513 - Movie collection(树状数组)

题目链接:点击打开链接 题意: 有编号1~n的n个影碟从上到下排列, 每次取一个影碟并把其放在最上面, 求每次取之前该影碟前面有多少个影碟. 取出影碟, 将该位置-1即可, 容易想到用树状数组来维护, 但是还要放到最前面. 其实解决方法很简单, 就是把数组开大一点, 前面留出足够大的空间, 不断更新位置即可. 细节参见代码: #include<cstdio> #include<cstring> #include<algorithm> #include<iostre

【二维树状数组】See you~

https://www.bnuoj.com/v3/contest_show.php?cid=9148#problem/F [题意] 给定一个矩阵,每个格子的初始值为1.现在可以对矩阵有四种操作: A x y n1 :给格点(x,y)的值加n1 D x y n1: 给格点(x,y)的值减n1,如果现在格点的值不够n1,把格点置0 M x1 y1 x2 y2:(x1,y1)移动给(x2,y2)n1个 S x1 y1 x2 y2 查询子矩阵的和 [思路] 当然是二维树状数组 但是一定要注意:lowbi

【树状数组+dp+离散化】Counting Sequences

https://www.bnuoj.com/v3/contest_show.php?cid=9149#problem/G [题意] 给定一个数组a,问这个数组有多少个子序列,满足子序列中任意两个相邻数的差(绝对值)都不大于d. [思路] 首先,朴素的dp思想: dp[i]为以a[i]结尾的子问题的答案,则dp[i]=sum(dp[k]),k<i&&|a[k]-a[i]|<=d 但是时间复杂度为O(n^2),会超时. 我们可以这样想: 如果数组a排好序后,dp[i]就是区间(a[

树状数组---Squared Permutation

BNUOJ   51636 最近,无聊的过河船同学在玩一种奇怪的名为“小Q的恶作剧”的纸牌游戏. 现在过河船同学手有张牌,分别写着,打乱顺序之后排成一行,位置从左往右按照标号. 接下来小Q同学会给出个操作,分为以下两种: 1.给定,交换从左往右数的第和第张牌, 2.给定,对从左往右数的第张牌,记下位置是这张牌上的数字的牌的数字,询问所有记下的数字加起来的结果. 虽然无聊的过河船同学精通四则运算,但是要完成这么大的计算量还是太辛苦了,希望你能帮他处理这些操作. Input 第一行是一个正整数,表示