• 【NOI2004T1】郁闷的出纳员-平衡树入门题


    题目:郁闷的出纳员

    做法:了解平衡树这个数据结构的人应该一眼就能看出这个题目可以用平衡树做(平衡树的教程网上太多了,这里就不赘述了),用平衡树维护插入、删除、查找第k小(注意由于题目中询问第k大,就是查找第(目前员工数-k+1)小)的操作即可,再用一个数delta来记录工资的整体变化量,注意处理就可以了。

    以下是本人代码:

    Treap 树堆(2016.8.10):

    #include <cstdio>
    #include <cstdlib>
    #include <ctime>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    int m,n,k,delta=0,root=0,cnt=0,ans=0;
    char op;
    struct node
    {
      int son[2],size,pri,key;
      void newnode()
      {
        son[0]=son[1]=0;
    	size=1;pri=rand();
      }
    }tree[100010];
    
    void rotate(int &v,bool p)
    {
      int x=tree[v].son[!p];
      tree[v].son[!p]=tree[x].son[p];
      tree[x].son[p]=v;
      tree[x].size=tree[v].size;
      tree[v].size=tree[tree[v].son[0]].size+tree[tree[v].son[1]].size+1;
      v=x;
    }
    
    void insert(int &v,int key)
    {
      if (v==0)
      {
        v=++cnt;
        tree[v].key=key;
    	tree[v].newnode();
      }
      else
      {
        tree[v].size++;
    	bool p=key<tree[v].key;
    	insert(tree[v].son[!p],key);
    	if (tree[v].pri<tree[tree[v].son[!p]].pri) rotate(v,p);
      }
    }
    
    int del(int &v,int key)
    {
      int t;
      if (v==0) return 0;
      if (tree[v].key<key)
      {
        t=tree[tree[v].son[0]].size+1;
    	v=tree[v].son[1];
    	return t+del(v,key);
      }
      else
      {
        t=del(tree[v].son[0],key);
    	tree[v].size-=t;
    	return t;
      }
    }
    
    int get_Kth(int &v,int k)
    {
      int s=tree[tree[v].son[0]].size+1;
      if (k<s) return get_Kth(tree[v].son[0],k);
      if (k>s) return get_Kth(tree[v].son[1],k-s);
      return tree[v].key;
    }
    
    int main()
    {
      srand(time(NULL));
      scanf("%d%d",&n,&m);getchar();
      while(n--)
      {
        scanf("%c%d",&op,&k);getchar();
    	if (op=='I')
    	{
    	  if (k>=m) insert(root,k-delta);
    	}
    	if (op=='A') delta+=k;
    	if (op=='S')
    	{
    	  delta-=k;
    	  ans+=del(root,m-delta);
    	}
    	if (op=='F')
    	{
    	  if (!root||k>tree[root].size) printf("-1
    ");
    	  else printf("%d
    ",get_Kth(root,tree[root].size-k+1)+delta);
    	}
      }
      printf("%d
    ",ans);
      
      return 0;
    }
    
    Splay Tree 伸展树(2016.8.26):

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    int n,m,root=0,top=0,delta=0,ans=0;
    int ch[100010][2],pre[100010],siz[100010],val[100010],c[100010],k;
    char op[20];
    
    void up(int x)
    {
      siz[x]=c[x]+siz[ch[x][0]]+siz[ch[x][1]];
    }
    
    void rotate(int x,int f)
    {
      int y=pre[x];
      ch[y][!f]=ch[x][f];
      pre[ch[x][f]]=y;
      pre[x]=pre[y];
      if (pre[x]) ch[pre[y]][ch[pre[y]][1]==y]=x;
      ch[x][f]=y;
      pre[y]=x;
      up(y);
    }
    
    void Splay(int x,int goal)
    {
      while(pre[x]!=goal)
      {
        if (pre[pre[x]]==goal) rotate(x,ch[pre[x]][0]==x);
    	else
    	{
    	  int y=pre[x],z=pre[y];
    	  int f=(ch[z][0]==y);
    	  if (ch[y][f]==x) rotate(x,!f),rotate(x,f);
    	  else rotate(y,f),rotate(x,f);
    	}
      }
      up(x);
      if (goal==0) root=x;
    }
    
    void newnode(int &v,int key,int f)
    {
      v=++top;
      val[v]=key;pre[v]=f;
      ch[v][0]=ch[v][1]=0;
      siz[v]=c[v]=1;
    }
    
    void insert(int &v,int key,int f)
    {
      if (!v)
      {
        newnode(v,key,f);
    	Splay(v,0);
    	return;
      }
      if (key==val[v])
      {
        c[v]++;siz[v]++;
    	Splay(v,0);
    	return;
      }
      insert(ch[v][key>val[v]],key,v);
      up(v);
    }
    
    int get_Kth(int x,int k)
    {
      int s=siz[ch[x][0]]+c[x];
      if (k<=s-c[x]) return get_Kth(ch[x][0],k);
      else if (k>s) return get_Kth(ch[x][1],k-s);
           else
    	   {
    	     Splay(x,0);
    		 return val[x];
    	   }
    }
    
    int getkey(int x,int key)
    {
      if (key<val[x]) return getkey(ch[x][0],key);
      else if (key>val[x]) return getkey(ch[x][1],key);
           else
    	   {
    	     Splay(x,0);
    		 return x;
    	   }
    }
    
    void rto(int k,int goal)
    {
      int x=root;
      while(1)
      {
        if (k<=siz[ch[x][0]]) x=ch[x][0];
    	else if (k>siz[ch[x][0]]+c[x]) {k-=siz[ch[x][0]]+c[x];x=ch[x][1];}
    	     else break;
      }
      Splay(x,goal);
    }
    
    void del_root()
    {
      int t=root;
      if (ch[root][1])
      {
        root=ch[root][1];
    	rto(1,0);
    	ch[root][0]=ch[t][0];
    	if (ch[t][0]) pre[ch[t][0]]=root;
      }
      else root=ch[root][0];
      pre[root]=0;
      up(root);
    }
    
    void Delete(int key)
    {
      int node=getkey(root,key);
      Splay(node,0);
      c[root]--;
      if (!c[root]) del_root();
    }
    
    int main()
    {
      scanf("%d%d",&n,&m);
      ch[0][0]=ch[0][1]=pre[0]=siz[0]=c[0]=val[0]=0;
      
      while(n--)
      {
        scanf("%s%d",op,&k);
    	if (op[0]=='I') {if (k>=m) insert(root,k-delta,0);}
    	if (op[0]=='A') delta+=k;
    	if (op[0]=='S')
    	{
    	  delta-=k;
    	  int Min;
    	  while(siz[root]&&(Min=get_Kth(root,1))<m-delta)
    	  {
    	    Delete(Min);
    	    ans++;
    	  }
    	}
    	if (op[0]=='F')
    	{
    	  if (siz[root]<k) printf("-1
    ");
    	  else printf("%d
    ",get_Kth(root,siz[root]-k+1)+delta);
    	}
      }
      printf("%d",ans);
      
      return 0;
    }
    
    (个人感觉这题用伸展树编程复杂度较高而且不如treap...也可能是我太渣了...毕竟伸展树有更加高能的作用...)


  • 相关阅读:
    填坑!!!virtualenv 中 nginx + uwsgi 部署 django
    树的遍历与递归
    Python 函数的参数
    virtualbox安装增强功能时【未能加载虚拟光盘】
    深入理解Python中的生成器
    Genymotion下载慢或者下载失败的解决办法
    Python3 多线程的两种实现方式
    Java 多线程
    关于"裁员与面试"的个人感悟吧
    三、由简单对象组装复杂实例的模式:建造者模式
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793925.html
Copyright © 2020-2023  润新知