Zoj 3635 <树状数组+二分>

题意:

给出n表示geeks人数..也是位置总数..

给出a1 a2 .. ai .. an 表示第 i 个人想要坐从左往右第 ai 个空位..

给出m表示询问的个数..

给出m个数b1 b2 .. bi .. bn 表示询问第 bi 个人的位置..

思路:

如果模拟过程..

应该是先按要求排好位置..然后输出位置值..

排好位置的过程就用到了二分..

用树状数组表示当前位置前有多少个空位..

然后二分找出满足当前位置前面空位有 ai 个的位置..

Tips:

记得安排好第i个geeks的位置后要modify树状数组..

Code:

 

View Code
 1 #include <stdio.h>

 2 #include <cstring>

 3 #include <algorithm>

 4 using namespace std;

 5 #define clr(x) memset(x, 0, sizeof(x))

 6 

 7 int n;       

 8 int c[100001]; 

 9 int lowbit(int x)

10 {

11    return (x)&(-x);

12 }

13 void modify(int pos,int x)

14 {

15     while(pos<=n)

16     {

17         c[pos]+=x;

18         pos+=lowbit(pos);

19     }

20 }

21 int getSum(int x)

22 {

23       int sum=0;

24       while(x>0)

25       {

26          sum+=c[x];

27          x-=lowbit(x);

28       }

29       return sum;

30 }

31 

32 int ans[50010];

33 int arr[50010];

34 int main()

35 {

36     int i, j, k;

37     int m, tmp;

38     while(scanf("%d", &n) != EOF)

39     {

40         clr(c);

41         clr(ans);

42         clr(arr);

43         for(i = 1; i <= n; ++i)

44         modify(i, 1);

45 

46         for(i = 1; i <= n; ++i){

47             scanf("%d", &tmp);

48             int r = n, l = 1, mid;

49             while(r > l)

50             {

51                 mid = (r+l)/2;

52                 if(getSum(mid) >= tmp) r = mid;

53                 else l = mid+1;

54             }

55             

56             arr[i] = r;

57             modify(r, -1);

58         }

59 

60 

61         scanf("%d", &m);

62         for(i = 0; i < m; ++i){

63             scanf("%d", &tmp);

64             ans[i] = arr[tmp];

65         }

66 

67         for(i = 0; i < m; ++i)

68         printf("%d%c", ans[i], i == m-1?'\n':' ');

69     }

70 

71     return 0;

72 }

 

 

 

你可能感兴趣的:(树状数组)