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

Description

Download as PDF
 

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$ \le$nm$ \le$100000): the number of movies in the stack and the number of locate requests.
  • one line with m integers a1,..., am(1$ \le$ai$ \le$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
题意有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 }

 

 

posted on 2014-07-24 16:22  huaihuaibuguai  阅读(448)  评论(0编辑  收藏  举报

导航