ZOJ Problem Set

题目大意

有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("
");
117   }
118   return 0;
119 }
原文地址:https://www.cnblogs.com/tsw123/p/4374894.html