ZOJ Problem Set - 3635
题目大意
有n个从1..n标号的座位,按时间顺序给出每个客人来的时候是坐在第几个空座位,最后给若干个询问问第i号客人坐在哪里
分析
线段树+二分
1 // Fast Sequence Operations II 2 // Rujia Liu 3 // 输入格式: 4 // n m 数组范围是a[1]~a[n],初始化为0。操作有m个 5 // 1 L R v 表示设a[L]=a[L+1]=...=a[R] = v。其中v > 0 6 // 2 L R 查询a[L]~a[R]的sum, min和max 7 #include<cstdio> 8 #include<cstring> 9 #include<algorithm> 10 using namespace std; 11 12 const int maxnode = 1<<17; 13 14 int _sum, _min, _max, op, qL, qR, v; 15 int vist[maxnode]; 16 struct IntervalTree { 17 int sumv[maxnode], minv[maxnode], maxv[maxnode], setv[maxnode]; 18 19 // 维护信息 20 void maintain(int o, int L, int R) { 21 int lc = o*2, rc = o*2+1; 22 if(R > L) { 23 sumv[o] = sumv[lc] + sumv[rc]; 24 minv[o] = min(minv[lc], minv[rc]); 25 maxv[o] = max(maxv[lc], maxv[rc]); 26 } 27 if(setv[o] >= 0) { minv[o] = maxv[o] = setv[o]; sumv[o] = setv[o] * (R-L+1); } 28 } 29 30 // 标记传递 31 void pushdown(int o) { 32 int lc = o*2, rc = o*2+1; 33 if(setv[o] >= 0) { //本结点有标记才传递。注意本题中set值非负,所以-1代表没有标记 34 setv[lc] = setv[rc] = setv[o]; 35 setv[o] = -1; // 清除本结点标记 36 } 37 } 38 39 void update(int o, int L, int R) { 40 int lc = o*2, rc = o*2+1; 41 if(qL <= L && qR >= R) { // 标记修改 42 setv[o] = v; 43 } else { 44 pushdown(o); 45 int M = L + (R-L)/2; 46 if(qL <= M) update(lc, L, M); else maintain(lc, L, M); 47 if(qR > M) update(rc, M+1, R); else maintain(rc, M+1, R); 48 } 49 maintain(o, L, R); 50 } 51 52 void query(int o, int L, int R) { 53 if(setv[o] >= 0) { // 递归边界1:有set标记 54 _sum += setv[o] * (min(R,qR)-max(L,qL)+1); 55 _min = min(_min, setv[o]); 56 _max = max(_max, setv[o]); 57 } else if(qL <= L && qR >= R) { // 递归边界2:边界区间 58 _sum += sumv[o]; // 此边界区间没有被任何set操作影响 59 _min = min(_min, minv[o]); 60 _max = max(_max, maxv[o]); 61 } else { // 递归统计 62 int M = L + (R-L)/2; 63 if(qL <= M) query(o*2, L, M); 64 if(qR > M) query(o*2+1, M+1, R); 65 } 66 } 67 }; 68 69 const int INF = 1000000000; 70 71 IntervalTree tree; 72 73 int main() { 74 int n, m,num; 75 while(scanf("%d", &n) !=EOF){ 76 memset(&tree, 0, sizeof(tree)); 77 memset(tree.setv, -1, sizeof(tree.setv)); 78 tree.setv[1] = 0; 79 v=1; 80 qL=1; 81 qR=n; 82 tree.update(1,1,n); 83 tree.query(1,1,n); 84 for(int i=1;i<=n;i++) 85 { 86 scanf("%d",&num); 87 qL=1;qR=n; 88 _sum = 0; 89 int l=1,r=n,mid; 90 while(l<r) 91 { 92 mid=(l+r)/2; 93 qR=mid; 94 tree.query(1, 1, n); 95 if(_sum>=num) 96 r=mid; 97 else 98 l=mid+1; 99 _sum = 0; 100 } 101 vist[i]=l; 102 v=0; 103 qL=l; 104 qR=l; 105 tree.update(1,1,n); 106 } 107 scanf("%d",&m); 108 for(int i=1;i<=m;i++) 109 { 110 scanf("%d",&num); 111 printf("%d",vist[num]); 112 if(i!=m) 113 printf(" "); 114 115 } 116 printf("\n"); 117 } 118 return 0; 119 }