SYSU-5, POJ 2131, 树状数组+二分

Posted 茶杯

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SYSU-5, POJ 2131, 树状数组+二分相关的知识,希望对你有一定的参考价值。

题目大意:给出n个人,顺序对位置进行请求,如果第i个人请求的位置上有人,则让这个人顺延,如果顺延的位置继续有人,递归进行,问最后所有人的位置。

解:这题貌似可以用平衡树+并查集搞定,但是我队友强烈安利树状数组的做法。赛场上没出,赛后结合discuz想了一下,作一下处理。

首先如果是一个请求第a[i]个有空位置的问题,那么这个问题显然可以用树状数组维护前缀和即可。所以我们现在考虑将原问题转化成这个问题。

考虑终态,把没有人的位置去掉,剩下的n个座位排在一起,显然转化成上面模型的形式

第i个询问时,如果我们记b[i] = 前i-1个询问里1~a[i]-1上有多少座位被请求,那么显然倒过来处理时,b[i]+1个位置即为所求位置(因为前面的人不会和后面的人抢位置,后面的人更优先确定,所以他的位置只取决于前面有多少空的,而他占掉座位后,如果前面的人请求了原意义上的同一位置,那么就在转化后的位置顺延即可,其实就是我们所提希望的转化模型,n个椅子,每次请求第b[i]个空椅子)

但是平衡树的做法真的很快(毕竟省一个二分的log),10s的时限我写了9.8s = =b,如果写完计算几何还有力气就琢磨一下平衡树的写法吧!

 

  1 #include <cstdio>
  2 #include <string>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <cmath>
  6 #include <cstring>
  7 #include <complex>
  8 #include <set>
  9 #include <vector>
 10 #include <map>
 11 #include <queue>
 12 #include <deque>
 13 #include <ctime>
 14 
 15 using namespace std;
 16 
 17 const double EPS = 1e-8;
 18 
 19 #define ABS(x) ((x)<0?(-(x)):(x))
 20 #define SQR(x) ((x)*(x))
 21 #define MIN(a,b) ((a)<(b)?(a):(b))
 22 #define MAX(a,b) ((a)>(b)?(a):(b))
 23 
 24 #define LSON(x) ((x)<<1)
 25 #define RSON(x) (((x)<<1)+1)
 26 #define LOWBIT(x) ((x)&(-(x)))
 27 #define MAXN 311111
 28 #define LL long long
 29 #define OO 214748364
 30 
 31 int a[MAXN], b[MAXN], f[MAXN], fa[MAXN];
 32 int n, m;
 33 
 34 struct TreeArray{
 35     int tree[MAXN], n;
 36     void clear(int lim = MAXN-10) {
 37         memset(tree, 0, sizeof(tree[0])*(lim+10));
 38         n = lim;
 39     }
 40     void add(int x, int num) {
 41         while (x <= n) {
 42             tree[x] += num;
 43             x += LOWBIT(x);
 44         }
 45     }
 46     int get(int x) {
 47         int res = 0;
 48         while (x) {
 49             res += tree[x];
 50             x -= LOWBIT(x);
 51         }
 52         return res;
 53     }
 54 } treeArray;
 55 
 56 int get(int x) {
 57 //    return x == fa[x] ? x : fa[x] = get(fa[x]);
 58     int t = x; while (t != fa[t]) t = fa[t];
 59     for (int i = x, j; i != t; i = j) {
 60         j = fa[x]; fa[x] = t;
 61     }
 62     return t;
 63 }
 64 
 65 int main() {
 66     freopen("test.txt", "r", stdin);
 67     scanf("%d%d", &n, &m); 
 68     treeArray.clear(n+m);
 69     for (int i = 1; i <= n+m; ++i) fa[i] = i;
 70     for (int i = 1; i <= n; ++i) {
 71         scanf("%d", a+i); 
 72         int t = get(a[i]); ++f[t];
 73         b[i] = treeArray.get(a[i]-1);
 74         treeArray.add(t, 1);
 75         fa[t] = t + 1; 
 76     }
 77 
 78     treeArray.clear(n+m);
 79     for (int i = 1; i <= n+m; ++i) {
 80         if (f[i] == 0) continue;
 81         treeArray.add(i, 1);
 82     }
 83 
 84     memset(a, 0, sizeof(a));
 85     for (int i = n; i; --i) {
 86         int l = 1, r = n+m, mid, t;
 87         while (l <= r) {
 88             mid = (l+r)>>1;
 89             if ((t = treeArray.get(mid)) == b[i]+1 && f[mid] == 1) {
 90                 treeArray.add(mid, -1); f[mid] = 0;
 91                 a[mid] = i; break;
 92             } else if (t < b[i]+1) {
 93                 l = mid + 1;
 94             } else {
 95                 r = mid - 1;
 96             }
 97         }
 98     }
 99     for (int i = MAXN-1; i; --i) if (a[i]) {
100         printf("%d\\n", i);
101         for (int j = 1; j <= i; ++j) printf("%d%c", a[j], j == i ? \'\\n\' : \' \');
102         break;
103     }
104     
105     return 0;
106 }
POJ 2131

 

以上是关于SYSU-5, POJ 2131, 树状数组+二分的主要内容,如果未能解决你的问题,请参考以下文章

POJ2182 Lost Cows (树状数组+二分)

POJ--2182剩余第K大(暴力/树状数组+二分)

POJ--2182剩余第K大(暴力/树状数组+二分)

POJ 2828 Buy Tickets (线段树 or 树状数组+二分)

POJ2182 Lost Cows 树状数组,二分

POJ_2886 Who Gets the Most Candies? 二分+树状数组