zoukankan      html  css  js  c++  java
  • BZOJ1208 [HNOI2004]宠物收养所 splay

    原文链接http://www.cnblogs.com/zhouzhendong/p/8085803.html


    题目传送门 - BZOJ1208


    题意概括

      有两种数,依次加入。

      规则为下:

      如果当前剩余的为同种数(或者没有数字),那么直接加入该数。

      否则找到与剩余的数中与当前数差的绝对值最小的(如果有多个一样小的,选择原值最小的),然后ans+=abs(差),并把这两个数都弄没。


    题解

      splay裸题。


    代码

    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <cstdlib>
    #include <cmath>
    using namespace std;
    const int N=80005,mod=1000000;
    int fa[N],son[N][2],val[N],root,total=0;
    void spt_clear(){
    	root=total=0;
    	memset(fa,0,sizeof fa);
    	memset(son,0,sizeof son);
    }
    int wson(int x){
    	return son[fa[x]][1]==x;
    }
    void rotate(int x){
    	if (fa[x]==0)
    		return;
    	int y=fa[x],z=fa[y],L=wson(x),R=L^1;
    	if (z)
    		son[z][wson(y)]=x;
    	fa[x]=z,fa[y]=x,fa[son[x][R]]=y;
    	son[y][L]=son[x][R],son[x][R]=y;
    }
    void splay(int x,int rt){
    	if (!x)
    		return;
    	if (!rt)
    		root=x;
    	for (int y=fa[x];fa[x];rotate(x),y=fa[x])
    		if (fa[y])
    			rotate(wson(x)==wson(y)?y:x);
    }
    int findpre(int v,int rt){
    	if (!rt)
    		return 0;
    	if (v==val[rt])
    		return rt;
    	if (v>val[rt]){
    		int x=findpre(v,son[rt][1]);
    		return x?x:rt;
    	}
    	return findpre(v,son[rt][0]);
    }
    int findpre(int v){
    	int res=findpre(v,root);
    	splay(res,0);
    	return res;
    }
    int findnxt(int v,int rt){
    	if (!rt)
    		return 0;
    	if (v==val[rt])
    		return rt;
    	if (v<val[rt]){
    		int x=findnxt(v,son[rt][0]);
    		return x?x:rt;
    	}
    	return findnxt(v,son[rt][1]);
    }
    int findnxt(int v){
    	int res=findnxt(v,root);
    	splay(res,0);
    	return res;
    }
    int find(int v,int rt){
    	if (!rt)
    		return 0;
    	if (v==val[rt])
    		return rt;
    	return find(v,son[rt][v>val[rt]]);
    }
    int findmax(int rt){
    	return son[rt][1]?findmax(son[rt][1]):rt;
    }
    void insert(int v,int &x,int pre){
    	if (x)
    		return insert(v,son[x][v>val[x]],x);
    	fa[x=++total]=pre,val[x]=v;
    	splay(x,0);
    }
    void erase(int v){
    	int x=find(v,root),rt;
    	splay(x,0);
    	if (!son[x][0]&&!son[x][1])
    		return spt_clear();
    	if (!son[x][0]||!son[x][1]){
    		int &s=son[x][(bool)son[x][1]];
    		fa[root=s]=0;
    		s=0;
    		return;
    	}
    	rt=findmax(son[x][0]);
    	son[x][0]=fa[son[x][0]]=0;
    	splay(rt,0);
    	fa[son[rt][1]=son[x][1]]=rt;
    	son[x][1]=0;
    }
    int n,op,v,ans=0,nowop;
    int main(){
    	spt_clear();
    	scanf("%d",&n);
    	for (int i=1;i<=n;i++){
    		scanf("%d%d",&op,&v);
    		if (root==0){
    			nowop=op;
    			insert(v,root,0);
    			continue;
    		}
    		if (op==nowop)
    			insert(v,root,0);
    		else {
    			int pre=findpre(v),nxt=findnxt(v),cv;
    			if (!pre)
    				cv=val[nxt];
    			else if (!nxt)
    				cv=val[pre];
    			else
    				cv=abs(val[nxt]-v)<abs(v-val[pre])?val[nxt]:val[pre];
    			ans=(ans+abs(v-cv))%mod;
    			erase(cv);
    		}
    	}
    	printf("%d",ans);
    	return 0;
    }
    

      

  • 相关阅读:
    Mysql查漏补缺
    RabbitMQ学习笔记
    memcache学习笔记
    Redis问题整理
    JedisCluster获取key所在的节点
    JavaSE编程题
    IDEA快捷键 日常整理
    Idea 常用快捷键列表
    【C++】 构造函数为什么不能声明为虚函数,析构函数可以
    【算法笔记】买卖股票问题--DP/贪心算法
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ1208.html
Copyright © 2011-2022 走看看