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 }
时间: 2024-10-29 19:12:19

ZOJ Problem Set - 3635的相关文章

ZOJ Problem Set - 3820 Building Fire Stations 【树的直径 + 操作 】

题目:problemId=5374" target="_blank">ZOJ Problem Set - 3820 Building Fire Stations 题意:给出n个点,n-1条边的一棵树.然后要在两个点上建立两个消防站.让全部点的到消防站最大距离的点的这个距离最小. 分析:首先先求这个树的直径.然后在树的直径的中点处把树分成两棵树.然后在把两棵树分别取中点的最大值就是ans值. 这个题目数据有点水了感觉... AC代码: #include <cstdi

ZOJ Problem Set - 1025解题报告

ZOJ Problem Set - 1025 题目分类:动态规划 原题地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1025   题目大意就是有很多木头,都有各自的长度和重量.现在要加工这些木头,如果加工某根木头的长度和重量大于等于它上一根木头的长度和重量,那么加工它不需要时 间,否则要花1分钟.现给出一堆木头的长度和重量,要求加工完这堆木头可以花的最少时间.例如给出5根木头长度重量分别为(4,9), (5,2),

ZOJ Problem Set - 3321 并查集

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3321 Circle Time Limit: 1 Second      Memory Limit: 32768 KB Your task is so easy. I will give you an undirected graph, and you just need to tell me whether the graph is just a circle.

ZOJ Problem Set - 3804 YY&#39;s Minions

学习:换一个角度考虑问题.YY's Minions Time Limit: 2 Seconds      Memory Limit: 65536 KB Despite YY's so much homework, she would like to take some time to play with her minions first. YY lines her minions up to an N*M matrix. Every minion has two statuses: awake

ZOJ Problem Set - 3195 Design the city 【Tarjan离线LCA】

题目:ZOJ Problem Set - 3195 Design the city 题意:给出一个图,求三点的连起来的距离. 分析:分别求出三点中任意两点的距离 / 2  = ans AC代码: #include <iostream> #include <cstdio> #include <cstring> #include <vector> using namespace std; #define N 50010 #define M 20010 struc

ZOJ Problem Set - 3229 Shoot the Bullet 【有上下界网络流+流量输出】

题目:ZOJ Problem Set - 3229 Shoot the Bullet 分类:有源有汇有上下界网络流 题意:有 n 天和 m 个girls,然后每天给一部分girls拍照,每个girls 有拍照的下限,即最少要拍这么多张,然后每天有k个女孩拍照,摄影师最多可以拍num张,然后 k 个女该每天拍照数量值有上下限,然后问你有没有满足这样条件的给女孩拍照的最大方案,然后按照输入输出每天给女孩拍照的张数. 做这道题目推荐先做:这儿 分析:首先它让你判断能不能满足条件. 按照题目给出的条件很

ZOJ Problem Set - 3203 Light Bulb 【三分法】

题目:ZOJ Problem Set - 3203 Light Bulb 题意: 如图,有个人在地上走,然后他的影子可以投影到墙上或者地上,问影子最长是多少? 分析: 我们知道,三分法是解决一个凹或凸函数的极大极小值,发现这个影子从刚好投影到右下角开始便是一个凸函数,他的影子长度是先递增后递减的,所以可以用三分法. 三分法的原理: AC代码: #include <cstdio> #include <cstring> #include <vector> #include

ZOJ Problem Set - 2563 Long Dominoes 【状压dp】

题目:ZOJ Problem Set - 2563 Long Dominoes 题意:给出1*3的小矩形,求覆盖m*n的矩阵的最多的不同的方法数? 分析:有一道题目是1 * 2的,比较火,链接:这里 这个差不多,就是当前行的状态对上一行有影响,对上上一行也有影响.所以 定义状态:dp[i][now][up]表示在第 i 行状态为now ,上一行状态为 up 时的方案数. 然后转移方程:dp[i][now][up] = sum ( dp[i-1][up][uup] ) 前提是合法 合法性的判断是比

ZOJ Problem Set - 2297 Survival 【状压dp】

题目:ZOJ Problem Set - 2297 Survival 题意:给出一些怪,有两个值,打他花费的血和可以增加的血,然后有一个boss,必须把小怪所有都打死之后才能打boss,血量小于0会死,也不能大于100. 分析:定义状态:dp[st],表示在 st 状态下的血量. 然后转移:dp[st] = max (dp[st],dp[st&~(1<<i )]+p[i].first - p[i].second); 注意初始化的时候必须在开始初始化,否则容易出错. #include &