UVA 11423 - Cache Simulator(树状数组)

UVA 11423 - Cache Simulator

题目链接

题意:题目讲的大概就是几个cash,每次操作可以加入一个或一些数据,如果数据之前有就是hit,命中后的数据就不会消失,如果没有就miss,当容量超过cash容量时,就会把之前最早没命中的一个丢掉,每次START就执行这些命令,计算miss次数并输出

思路:由于最多就2^24的数据,所以可以开一个树状数组,每个位置表示第i个添加进去的数据,并且把每个数据对应的位置记录下来,下次如果添加到一个之前有的数据,就利用树状数组查询上一次到这一次之间一共有多少个数据,如果数据超过cash大小,那么就说明上一次的已经被丢弃,就会多一次miss,然后hit成功后就把上一次的数据位置-1,把这个数据定在当前添加位置+1。注意每次START的时候要重新计算一次

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

#define lowbit(x) (x&(-x))

const int N = 35;
const int MAXN = (1<<24) + 5;
int n, cach[N], bit[MAXN];

void add(int x, int v) {
    while (x < MAXN) {
	bit[x] += v;
	x += lowbit(x);
    }
}

int get(int x) {
    int ans = 0;
    while (x) {
	ans += bit[x];
	x -= lowbit(x);
    }
    return ans;
}

int get(int l, int r) {
    return get(r) - get(l - 1);
}

char op[10];
int ans[N], vis[MAXN], now;

void init() {
    now = 0;
    memset(bit, 0, sizeof(bit));
    memset(vis, 0, sizeof(vis));
    for (int i = 0; i < n; i++)
	scanf("%d", &cach[i]);
}

void tra(int num) {
    if (vis[num]) {
	int len = get(vis[num], now);
	for (int i = 0; i < n; i++) {
	    if (cach[i] >= len) break;
	    ans[i]++;
	}
	add(vis[num], -1);
    }
    else {
	for (int i = 0; i < n; i++)
	    ans[i]++;
    }
    add(vis[num] = ++now, 1);
}

void solve() {
    int x, b, y, nn;
    while (scanf("%s", op)) {
	if (op[0] == 'E') break;
	if (op[0] == 'S') {
	    for (int i = 0; i < n; i++)
		printf("%d%c", ans[i], i == n - 1 ? '\n' : ' ');
	    memset(ans, 0, sizeof(ans));
	}
	if (op[0] == 'A') {
	    scanf("%d", &x);
	    tra(x);
	}
	if (op[0] == 'R') {
	    scanf("%d%d%d", &b, &y, &nn);
	    for (int i = 0; i < nn; i++)
		tra(b + y * i);
	}
    }
}

int main() {
    while (~scanf("%d", &n)) {
	init();
	solve();
    }
    return 0;
}

UVA 11423 - Cache Simulator(树状数组),布布扣,bubuko.com

时间: 2024-10-11 18:20:08

UVA 11423 - Cache Simulator(树状数组)的相关文章

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

UVa 1513 Movie collection (树状数组)

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

UVA 10869 - Brownie Points II(树状数组)

UVA 10869 - Brownie Points II 题目链接 题意:平面上n个点,两个人,第一个人先选一条经过点的垂直x轴的线,然后另一个人在这条线上穿过的点选一点作垂直该直线的线,然后划分出4个象限,第一个人得到分数为1,3象限,第二个人为二四象限,问第一个个人按最优取法,能得到最小分数的最大值,和这个值下另一个人的得分可能情况 思路:树状数组,可以枚举一点,如果能求出右上和左下点的个数就好办了,其实用一个树状数组,把y坐标离散化掉,然后记录进来,然后把点按x从左往右,每次删掉点后查询

UVA 11525 Permutation(树状数组)

题目意思是说  给你一个数k  然后有k个si   问你1--k 的第n个全排列是多少   注意是 1 2 3...k的全排列 不是si的 N=   由观察得知(k-i)!就是k-i个数字的全排列种数, 0=<Si<=k-i,所以显然可知假设当i==1时从第(k-1)!*s1到第n个全排列都是由第S1+1个数字开始的数列,因为每(k-1)!次排列过后,下一个排列的第1个数字都要增大1(每隔(k-1)!次,这k-1个数字都排列过一遍了,下一次只能增大更前面一个,也就是第1个了) 比如对于数列{1