• 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 }
  • 相关阅读:
    组合 聚合 依赖 关联
    effective C++ 总结
    重讲设计模式
    宏定义要加括号
    enum hack
    MFC 刷新函数:Invaldate,UpdateWindow,InvaldateRect
    MFC onchar()
    win7系统自带分区工具,能分出逻辑分区
    窗口的创建步骤
    私话编译连接运行过程以及动态库、静态库
  • 原文地址:https://www.cnblogs.com/tsw123/p/4374894.html
Copyright © 2020-2023  润新知