zoukankan      html  css  js  c++  java
  • 【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...也可能是我太渣了...毕竟伸展树有更加高能的作用...)


  • 相关阅读:
    POJ 1953 World Cup Noise
    POJ 1995 Raising Modulo Numbers (快速幂取余)
    poj 1256 Anagram
    POJ 1218 THE DRUNK JAILER
    POJ 1316 Self Numbers
    POJ 1663 Number Steps
    POJ 1664 放苹果
    如何查看DIV被设置什么CSS样式
    独行DIV自适应宽度布局CSS实例与扩大应用范围
    python 从入门到精通教程一:[1]Hello,world!
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793924.html
Copyright © 2011-2022 走看看