ZOJ 2112 Dynamic Rankings(動態區間第 k 大+塊狀鏈表)

 

題目大意

 

給定一個數列,編號從 1 到 n,如今有 m 個操做,操做分兩類:ios

  1. 修改數列中某個位置的數的值爲 val數組

  2. 詢問 [L, R] 這個區間中第 k 大的是多少ide

n<=50,000   m<=10,000spa

 

作法分析

 

本覺得某一天我會用 splay 或者 樹套樹 去搞的,結果被用塊狀鏈表搞了code

其實這題和鏈表沒什麼關係,利用了塊狀鏈表分塊操做的思想blog

 

首先,看看數據規模:n<=50,000,那麼,咱們每一塊的大小能夠設置爲 sqrt(n) 大概 230 的樣子排序

用一個數組 A 存儲整個數列,將數列分塊的保存在鏈表中,每塊大小爲 230,而且,每個塊都從小到大排序,這樣的複雜度是 sqrt(n)*sqrt(n)*log2(sqrt(n))get

 

對於修改操做,先將 A 數組對應的位置的值改了,而後找到對應的分塊中,修改並排序,這裏能夠使用插入排序,也能夠直接暴力的調用快排,若是直接調用快排,這裏的複雜度是 sqrt(n)*log2(sqrt(n)) 的cmd

 

對於查詢操做:假設查詢的是區間 [L, R],先把區間開頭和結尾的不在一個整塊中的提出去組成一個新塊並排序,把在區間中的整塊也提出去,這樣,當前的詢問操做就是在這些塊中詢問了,這樣之後在二分答案,依次在每個塊中尋找不大於當前答案的數是多大,在每個塊中詢問的時候,能夠使用二分,這樣快點string

查詢的時間複雜度比較難算,大概是:log2(MAX_INTEGER)*sqrt(n)*log2(sqrt(n)) 差很少是 32*225*8 大概 10^4 的樣子

 

那麼,總的時間複雜度大概爲 M*log2(MAX_INTEGER)*sqrt(n)*log2(sqrt(n)) 爲 10^8 級別,題目給了 10 秒,在 zoj 上,這個時間複雜度仍是能夠去試試的

因而過了,5秒多...

 

參考代碼

 

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <vector>
  5 #include <algorithm>
  6 
  7 using namespace std;
  8 
  9 const int N=50004, LEN=230, INF=0x3fffffff;
 10 
 11 struct Block_List {
 12     struct Node {
 13         int buff[LEN], Size;
 14         void init() {
 15             memset(buff, 0, sizeof buff);
 16             Size=0;
 17         }
 18     } List[LEN];
 19     int tot;
 20 
 21     void init(int n, int A[]) {
 22         List[0].init(), tot=1;
 23         for(int i=0, cur=0; i<n; ) {
 24             for(int j=0; i<n && j<LEN; j++, i++) {
 25                 List[cur].buff[j]=A[i];
 26                 List[cur].Size++;
 27             }
 28             if(i==n) continue;
 29             List[tot++].init();
 30             cur++;
 31         }
 32         for(int i=0; i<tot; i++) sort(List[i].buff, List[i].buff+List[i].Size);
 33     }
 34 
 35     void update(int id, int old, int val) {
 36         for(int i=0; i<List[id].Size; i++) if(List[id].buff[i]==old) {
 37             List[id].buff[i]=val;
 38             break;
 39         }
 40         sort(List[id].buff, List[id].buff+List[id].Size);
 41     }
 42 
 43     int query(int id, int val) {
 44         int L=0, R=List[id].Size-1;
 45         while(L<R) {
 46             int mid=(L+R)>>1;
 47             if(List[id].buff[mid]>val) R=mid;
 48             else L=mid+1;
 49         }
 50         if(List[id].buff[L]>val) L--;
 51         return L+1;
 52     }
 53 
 54     void NewNode(int id, int A[], int L, int R) {
 55         List[id].init();
 56         for(int i=L; i<=R; i++) List[id].buff[i-L]=A[i];
 57         List[id].Size=R-L+1;
 58         sort(List[id].buff, List[id].buff+List[id].Size);
 59     }
 60 };
 61 
 62 int A[N], n, m, t;
 63 Block_List hehe;
 64 char cmd[10];
 65 vector <int> tub;
 66 
 67 int main() {
 68 //    freopen("in", "r", stdin);
 69     scanf("%d", &t);
 70     for(int ca=1; ca<=t; ca++) {
 71         scanf("%d%d", &n, &m);
 72         for(int i=0; i<n; i++) scanf("%d", &A[i]);
 73         hehe.init(n, A);
 74         for(int i=0, a, b, c; i<m; i++) {
 75             scanf("%s", cmd);
 76             if(cmd[0]=='Q') {
 77                 scanf("%d%d%d", &a, &b, &c);
 78                 a--, b--;
 79                 int id1=a/LEN, id2=b/LEN;
 80                 tub.clear();
 81                 if(id1==id2) {
 82                     hehe.NewNode(hehe.tot, A, a, b);
 83                     tub.push_back(hehe.tot);
 84                 }
 85                 else {
 86                     hehe.NewNode(hehe.tot, A, a, (id1+1)*LEN-1);
 87                     hehe.NewNode(hehe.tot+1, A, id2*LEN, b);
 88                     tub.push_back(hehe.tot);
 89                     tub.push_back(hehe.tot+1);
 90                     for(int i=id1+1; i<id2; i++) tub.push_back(i);
 91                 }
 92                 int L=0, R=INF;
 93                 while(L<R) {
 94                     int mid=(L+R)>>1;
 95                     int sum=0;
 96                     for(int i=0, len=(int)tub.size(); i<len; i++) {
 97                         sum+=hehe.query(tub[i], mid);
 98                     }
 99                     if(sum<c) L=mid+1;
100                     else R=mid;
101                 }
102                 printf("%d\n", L);
103             }
104             else {
105                 scanf("%d%d", &a, &b);
106                 a--;
107                 hehe.update(a/LEN, A[a], b);
108                 A[a]=b;
109             }
110         }
111     }
112     return 0;
113 }
ZOJ 2112

 

題目連接 & AC 通道

 

ZOJ 2112 Dynamic Rankings

相關文章
相關標籤/搜索