BZOJ 1826: [JSOI2010]缓存交换
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1826
分析:
贪心+堆或者平衡树(以下统一称为树)。越在后面,切换他是最好的。。。
1.当已经在树上的时候,换掉之前已在树上的该主存块,换成当前主存块的下一个出现的位置。
2.当前可用的cache足够的时候,直接插入到树中。
3.每次需要切换cache的时候,都切掉距离当前位置最远的那个主存块,然后将当前的cache的下一次出现的位置更新到树上。
先离散化,然后使用池子法从后往前扫,这样就可以统计每个主存块下一次出现的位置,插入的时候,直接插入的是当前主存块的下一个他出现的位置
| 329452 | yejinru | 1826 | Accepted | 7048 kb | 404 ms | C++/Edit | 4397 B | 2012-12-16 10:32:33 |
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
using namespace std;
const int X = 100005;
#define debug puts("here");
int tot;
struct node{
int l,r,s,val;
void init(int _val){
l = r = 0;
s = 1;
val = _val;
}
}sbt[X];
void left_rotate(int &t){
int k = sbt[t].r;
sbt[t].r = sbt[k].l;
sbt[k].l = t;
sbt[k].s = sbt[t].s;
sbt[t].s = sbt[sbt[t].l].s+sbt[sbt[t].r].s+1;
t = k;
}
void right_rotate(int &t){
int k = sbt[t].l;
sbt[t].l = sbt[k].r;
sbt[k].r = t;
sbt[k].s = sbt[t].s;
sbt[t].s = sbt[sbt[t].l].s+sbt[sbt[t].r].s+1;
t = k;
}
void maintain(int &t,bool ok){
if(!ok){
if(sbt[sbt[sbt[t].l].l].s>sbt[sbt[t].r].s)
right_rotate(t);
else if(sbt[sbt[sbt[t].l].r].s>sbt[sbt[t].l].s){
left_rotate(sbt[t].l);
right_rotate(t);
}
else return;
}
else{
if(sbt[sbt[sbt[t].r].r].s>sbt[sbt[t].l].s)
left_rotate(t);
else if(sbt[sbt[sbt[t].r].l].s>sbt[sbt[t].l].s){
right_rotate(sbt[t].r);
left_rotate(t);
}
else return;
}
maintain(sbt[t].l,0);
maintain(sbt[t].r,1);
maintain(t,0);
maintain(t,1);
}
void insert(int &t,int val){
if(!t){
t = ++tot;
sbt[t].init(val);
return;
}
sbt[t].s++;
if(val<sbt[t].val)
insert(sbt[t].l,val);
else
insert(sbt[t].r,val);
maintain(t,val>=sbt[t].val);
}
int del(int &t,int val){
if(!t) return 0;
sbt[t].s--;
if(val==sbt[t].val||(val<sbt[t].val&&!sbt[t].l)||(val>sbt[t].val&&!sbt[t].r)){
if(sbt[t].l&&sbt[t].r){
int pos = del(sbt[t].l,val+1);
sbt[t].val = sbt[pos].val;
return pos;
}
else{
int pos = t;
t = sbt[t].l+sbt[t].r;
return pos;
}
}
return del(val<sbt[t].val?sbt[t].l:sbt[t].r,val);
}
int find_max(int t){
while(sbt[t].r)
t = sbt[t].r;
return sbt[t].val;
}
int find(int t,int val){
if(!t)
return 0;
if(sbt[t].val==val)
return true;
if(sbt[t].val>val)
return find(sbt[t].l,val);
return find(sbt[t].r,val);
}
int a[X],n;
map<int,int> ma;
int po[X],tol,Next[X];
int main(){
int n,m;
int inf = 100000000;
while(cin>>n>>m){
tot = 0;
ma.clear();
int cnt = 0;
int x,y;
int root = 0;
tol = n;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
if(ma[a[i]]==0) //使用map离散化
ma[a[i]] = ++cnt;
po[i] = ++tol;
}
for(int i=n;i;i--){
x = ma[a[i]];
Next[i] = po[x]; //池子法,从后往前扫
po[x] = i;
}
cnt = 0;
int ans = 0;
for(int i=1;i<=n;i++){
if(find(root,i)){ //已存在树中,直接删除后更新
del(root,i);
insert(root,Next[i]);
}
else{
ans ++;
if(cnt==m) //cache数不够了,需要删除
del(root,find_max(root));
else //够用的话,但是需要插入,cache已使用的数目加一
cnt ++;
insert(root,Next[i]);//插入当前主存块的下一个位置
}
}
cout<<ans<<endl;
}
return 0;
}

浙公网安备 33010602011771号