超市促銷 treap or hash

突然發現幾月前刷的此題

本着刷道水題的想法我就用treap虐了它一遍


題目描述: 
促銷活動遵循以下原則:“參與本活動的顧客,應將自己的個人信息寫在所付帳單背面,
並將賬單投入指定的箱子。在每天的銷售結束後,箱子中消費金額最大和最小的兩張賬單將
被選出。消費最多的顧客將得到一筆獎金,獎金的數目等於兩張賬單金額之差。爲了避免因
爲一次消費而得到多筆獎金,依照以上原則選出的兩張賬單將不會被放回到箱子中,但箱子
裏剩下的賬單可以繼續參加第二天的活動。” 
你的任務是根據每天投入箱子的所有帳單,計算出整個促銷活動中找是要付出的獎金總
額。本題中約定: 
1. 整個出銷活動持續了 N 天,N≤5000。 
2. 第 i 天放入的鈔票有 a[i]張,a[i]≤10^5,且 S=Σa[i]≤10^6。 
3. 第 i 天放入的鈔票面值分別是 bi[1],bi[2],…,bi[a[i]],b[j] ≤10^6。 
輸入格式: 
輸入文件的第一行的正整數 N 表示爲此次促銷活動持續的天數。接下來的 N 行含有一連
串用單個空格隔開的非負數。第 I+1 行的數字表示在第 I 天促銷活動中放入投票箱內帳單的
價格。此行的第一個整數 K 表示這一天放入投票箱內的帳單數,接着的 K 個正整數分別代表
着每張帳單的價格。 
輸出格式: 
 
輸出文件中恰含有一整數,它的值等於此次促銷活動用作獎勵的總花費。 
樣例: 
pro.in: 
5 
3 1 2 3 
2 1 1 
4 10 5 5 1 
0 
1 2 
pro.out: 
19 


trep code

#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <iostream>
using namespace std;
#define Rand() (rand () * rand () * rand () % 10000000)

const int maxn = 1000000 + 5;

class Treap_tree
{
   public :
      Treap_tree()
      {
         e = root = tot = 0;
      }
      void Left_Rotate(int &rt)
      {
         int y = Right[rt];
         Right[rt] = Left[y];
         Left[y] = rt;
         rt = y;
      }

      void Right_Rotate(int &rt)
      {
         int y = Left[rt];
         Left[rt] = Right[y];
         Right[y] = rt;
         rt = y;
      }

      void Insert(int &rt, int y)
      {
         if (!rt)
         {
            ++e;
            Left[e] = Right[e] = 0;
            Fix[e] = Rand();
            Value[e] = y;
            rt = e;
         } 
         else
         {
            if (y < Value[rt])
            {
               Insert(Left[rt], y);
               if (Fix[Left[rt]] > Fix[rt]) Right_Rotate(rt);
            } 
            else if ( y >= Value[rt])
            {
               Insert(Right[rt], y);
               if (Fix[Right[rt]] > Fix[rt]) Left_Rotate(rt);
            }
         }
      }

      void Search_Max(int &rt)
      {
         if (Right[rt])
            Search_Max(Right[rt]);
         else
         {
            MAX = Value[rt];
            rt = Left[rt];
         }
      }

      void Search_Min(int &rt)
      {
         if (Left[rt])
            Search_Min(Left[rt]);
         else
         {
            MIN = Value[rt];
            rt = Right[rt];
         }
      }

      long long work()
      {
         cin >> n;
         for (int i=1; i<=n; ++i)
         {
            int x, y;
            scanf("%d", &x);
            for (int j=1; j<=x; ++j)
            {
               scanf("%d", &y);
               Insert(root, y);
            }
            Search_Max(root);
            if (!root) 
               MIN = MAX;
            else 
               Search_Min(root);
            tot += MAX - MIN;
         }
         return tot;
      }

   private :
      int MAX, MIN;
      int n, e, root;
      long long tot;
      int Left[maxn], Right[maxn], Fix[maxn], Value[maxn];
};
Treap_tree treap;

int main()
{
   srand((unsigned)time(0));
   freopen("pro.in", "r", stdin);
   freopen("pro.out", "w", stdout);
   cout << treap.work();
   return 0;
}


不過此題平衡樹常數註定常數很大 70分能拿到

其他的方法是hash or 分段hash

1.hash 複雜度是O(S + NM) M爲最大數字

2.分段hash 複雜度O(S + N*M^(1/2))

分段hash是此題正解

但用hash我的數據也可AC

我的hash巧妙在每次操作記錄了當前Min, Max;

讀入時也適當更新

接着掃描則可優化較多了


hash code

#include <cmath>
#include <cstdio>
#include <climits>
#include <cstdlib>
#include <iostream>
using namespace std;
#define maxn 1000005

int n;
int hash[maxn];
__int64 tot = 0;
int Min = INT_MAX, Max = -INT_MAX;

int main()
{
   int x,y;
   freopen("pro.in", "r", stdin);
   freopen("pro.out", "w", stdout);
   scanf("%d", &n);
   for (int i=1; i<=n; i++)
   {
      scanf("%d", &x);
      for (int j=1;j<=x;j++)
      {
         scanf("%d",&y);
         ++hash[y];
         Min = (Min > y) ? y : Min;
         Max = (Max < y) ? y : Max;
      }
      if (!hash[Max])
      {
         for (int j=Max-1; j>=1; --j)
            if (hash[j]) { Max=j; break; }
      }
      if (!hash[Min])
      {
         for (int j=Min+1; j<=maxn; ++j)
            if (hash[j]) { Min=j;break; }
      }
      tot += Max - Min;
      hash[Max]--; hash[Min]--;
   }
   printf("%I64d", tot);
   return 0;
}

數據奉上

http://pan.baidu.com/share/link?shareid=22451&uk=2652110486


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章