• 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;
    }
    

      

  • 相关阅读:
    如何做一个富文本编辑器
    chrome插件开发示例
    使用github Pages和Jekyll搭建一个Blog
    使用JavaScript制作简单的动画
    JQuery模拟七------利用extend包装ajax实现
    JQuery模拟六------jQuery处理事件简化版
    JQuery模拟五------实现属性set&get和CSS set&get
    JQuery模拟四------把用到Sizzle的地方先用CSS3选择器实现
    JQuery模拟三------利用extend函数扩展jQuery自身的方法和浏览器判断
    JQuery模拟二------添加extend函数和简单选择器
  • 原文地址:https://www.cnblogs.com/yejinru/p/2820354.html
Copyright © 2020-2023  润新知