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

题意:给你n盘歌碟按照(1....n)从上到下放,接着m个询问,每一次拿出x碟,输出x上方有多少碟并将此碟放到开头

直接想其实就是一线段的区间更新,单点求值,但是根据题意我们可以这样想

首先我们倒着存  n--1,接着每次询问时把放碟子放到最后,这样我们要开一个映射数组映射每个碟子在哪个位置

其中我们需要使用树状数组维护每个绝对位置是否有碟子(有些碟子已经放到了后面了),再使用区间求和就好了

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<string>
#include<cstdio>
#include<cstring>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define eps 1E-8
/*注意可能会有输出-0.000*/
#define Sgn(x) (x<-eps? -1 :x<eps? 0:1)//x为两个浮点数差的比较,注意返回整型
#define Cvs(x) (x > 0.0 ? x+eps : x-eps)//浮点数转化
#define zero(x) (((x)>0?(x):-(x))<eps)//判断是否等于0
#define mul(a,b) (a<<b)
#define dir(a,b) (a>>b)
typedef long long ll;
typedef unsigned long long ull;
const int Inf=1<<28;
const double Pi=acos(-1.0);
const int Mod=1e9+7;
const int Max=200010;//开成两倍,因为要向后添加
int mp[Max],bit[Max],tot,tol;//映射位置 被映射的树状数组 总大小
int lowbit(int x)
{
    return x&(-x);
}
void Add(int x,int y)
{
    while(x<=tol)
    {
        bit[x]+=y;
        x+=lowbit(x);
    }
    return ;
}
int Sum(int x)
{
    int sum=0;
    while(x)
    {
        sum+=bit[x];
        x-=lowbit(x);
    }
    return sum;
}
void Init(int n,int m)
{
    memset(bit,0,sizeof(bit));
    tot=n;
    tol=n+m;
    for(int i=1; i<=n; ++i)//倒序存储
    {
        mp[i]=n-i+1;
        Add(mp[i],1);
    }
    return;
}
int Solve(int n,int m)
{
    ll ans=0;
    int pos=mp[m];
    //printf("\npos=%d\n",pos);
    ans=n-Sum(pos);//求后面的
    tot++;
    Add(pos,-1);//更新
    Add(tot,1);
    mp[m]=tot;//映射到开头
    return ans;
}
int main()
{
    int t,n,m,num;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d %d",&n,&m);
        Init(n,m);
        for(int i=0;i<m;++i)
        {
            scanf("%d",&num);
            printf("%d%c",Solve(n,num),i==m-1?‘\n‘:‘ ‘);
        }
    }
    return 0;
}
时间: 2024-11-03 05:41:15

UVA 1513 Movie collection (树状数组+反向存储)的相关文章

UVa 1513 Movie collection (树状数组)

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

UVA 11423 - Cache Simulator(树状数组)

UVA 11423 - Cache Simulator 题目链接 题意:题目讲的大概就是几个cash,每次操作可以加入一个或一些数据,如果数据之前有就是hit,命中后的数据就不会消失,如果没有就miss,当容量超过cash容量时,就会把之前最早没命中的一个丢掉,每次START就执行这些命令,计算miss次数并输出 思路:由于最多就2^24的数据,所以可以开一个树状数组,每个位置表示第i个添加进去的数据,并且把每个数据对应的位置记录下来,下次如果添加到一个之前有的数据,就利用树状数组查询上一次到这

uva 1428 - Ping pong(树状数组)

题目链接:uva 1428 - Ping pong 题目大意:一条大街上住着n个乒乓球爱好者,经常组织比赛.每个人都有一个不同的能力值,每场比赛需要3个人,裁判要住在两个选手之间,并且能力值也要在选手之间,问说最多能举行多少场比赛. 解题思路:预处理出bi和ci分别表示说在1~i中能力值比第i个人小的人和i+1~n中能力值比第i个人小的.处理过程用树状数组维护即可. #include <cstdio> #include <cstring> #include <algorith

UVA 10909 - Lucky Number(树状数组)

UVA 10909 - Lucky Number 题目链接 题意:问一个数字能否由两个lucky num构造出来,lucky num根据题目中的定义 思路:利用树状数组找前k大的方法可以构造出lucky num的序列,然后每次查找n,就从n / 2开始往下查找即可 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 2000001

Permutation UVA - 11525(值域树状数组,树状数组区间第k大(离线),log方,log)

Permutation UVA - 11525 看康托展开 题目给出的式子(n=s[1]*(k-1)!+s[2]*(k-2)!+...+s[k]*0!)非常像逆康托展开(将n个数的所有排列按字典序排序,并将所有排列编号(从0开始),给出排列的编号得到对应排列)用到的式子.可以想到用逆康托展开的方法.但是需要一些变化: for(i=n;i>=1;i--) { s[i-1]+=s[i]/(n-i+1); s[i]%=(n-i+1); } 例如:n=3时,3=0*2!+0*1!+3*0!应该变为3=1

uva 11525排列(树状数组 + 二分)

 现在给定k和n,要你按字典序输出 第n种排列的数列 而且题目给的 n是 n=S1(k-1)!+S2(k-2)!+...+Sk-1*1!+Sk*0!(0=<Si<=k-i), 我们可以知道si表示i后面有多少个比a[i]小的数,这样一来首先想到的就是set,但是set不能顺序访问,所以可以用树状数组,初始时置1,消除后置0,然后二分来求和为si + 1的位置 代码如下: #include<cstdio> #include<cstring> #include<c

uva 12356 Army Buddies 树状数组解法 树状数组求加和恰为k的最小项号 难度:1

Nlogonia is fighting a ruthless war against the neighboring country of Cubiconia. The Chief General of Nlogonia's Army decided to attack the enemy with a linear formation of soldiers, that would advance together until conquering the neighboring count

UVA - 1471 Defense Lines 树状数组/二分

                              Defense Lines After the last war devastated your country, you - as the king of the land of Ardenia - decided it washigh time to improve the defense of your capital city. A part of your forti?cation is a line of magetower

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