SPOJ Meteors - 可持久化线段树 - 二分法

Byteotian Interstellar Union (BIU) has recently discovered a new planet in a nearby galaxy. The planet is unsuitable for colonisation due to strange meteor showers, which on the other hand make it an exceptionally interesting object of study.

The member states of BIU have already placed space stations close to the planet's orbit. The stations' goal is to take samples of the rocks flying by. The BIU Commission has partitioned the orbit into  sectors, numbered from  to , where the sectors  and  are adjacent. In each sector there is a single space station, belonging to one of the  member states.

Each state has declared a number of meteor samples it intends to gather before the mission ends. Your task is to determine, for each state, when it can stop taking samples, based on the meter shower predictions for the years to come.

Input

The first line of the standard input gives two integers,  and  (), separated by a single space, that denote, respectively, the number of BIU member states and the number of sectors the orbit has been partitioned into.

In the second line there are  integers  (), separated by single spaces, that denote the states owning stations in successive sectors.

In the third line there are  integers  (), separated by single spaces, that denote the numbers of meteor samples that the successive states intend to gather.

In the fourth line there is a single integer  () that denotes the number of meteor showers predictions. The following  lines specify the (predicted) meteor showers chronologically. The -th of these lines holds three integers (separated by single spaces), which denote that a meteor shower is expected in sectors  (if ) or sectors  (if ), which should provide each station in those sectors with  meteor samples ().

Output

Your program should print  lines on the standard output. The -th of them should contain a single integer , denoting the number of shower after which the stations belonging to the -th state are expected to gather at least  samples, or the wordNIE (Polish for no) if that state is not expected to gather enough samples in the foreseeable future.

Example

For the input data:

3 5
1 3 2 1 3
10 5 7
3
4 2 4
1 3 1
3 5 2

the correct result is:

3
NIE
1

  题目大意 一个星球的环形轨道上有m个空间站,每个空间站属于n个国家中的一个,有k次流星雨,每次会使得一段空间站可以获得一些陨石,每个国家有个收集目标,问每个国家在第多少次流星雨后达成目标,或者无法达到目标。

  将每次流星雨当成一次区间修改,修改可持久化线段树。用vector存下每个国家有哪些空间站。

  然后枚举每个国家,二分答案,判断的时候暴力枚举每个国家的空间站,进行查询。

  好在spoj不卡空间,bzoj空间直接卡死。然后我发现似乎我算节点数的时候忘记算常数了,发现内存池开小了很多,所以就动态开节点慢了许多。

Code

  1 /**
  2  * SPOJ
  3  * Problem#METEORS
  4  * Accepted
  5  * Time:3220ms
  6  * Memory:521216k
  7  */
  8 #include <iostream>
  9 #include <cstdio>
 10 #include <ctime>
 11 #include <cmath>
 12 #include <cctype>
 13 #include <cstring>
 14 #include <cstdlib>
 15 #include <fstream>
 16 #include <sstream>
 17 #include <algorithm>
 18 #include <map>
 19 #include <set>
 20 #include <stack>
 21 #include <queue>
 22 #include <vector>
 23 #include <stack>
 24 #ifndef WIN32
 25 #define Auto "%lld"
 26 #else
 27 #define Auto "%I64d"
 28 #endif
 29 using namespace std;
 30 typedef bool boolean;
 31 const signed int inf = (signed)((1u << 31) - 1);
 32 const double eps = 1e-6;
 33 const int binary_limit = 128;
 34 #define smin(a, b) a = min(a, b)
 35 #define smax(a, b) a = max(a, b)
 36 #define max3(a, b, c) max(a, max(b, c))
 37 #define min3(a, b, c) min(a, min(b, c))
 38 template<typename T>
 39 inline boolean readInteger(T& u){
 40     char x;
 41     int aFlag = 1;
 42     while(!isdigit((x = getchar())) && x != '-' && x != -1);
 43     if(x == -1) {
 44         ungetc(x, stdin);    
 45         return false;
 46     }
 47     if(x == '-'){
 48         x = getchar();
 49         aFlag = -1;
 50     }
 51     for(u = x - '0'; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - '0');
 52     ungetc(x, stdin);
 53     u *= aFlag;
 54     return true;
 55 }
 56 
 57 #define LL long long
 58 
 59 typedef class SegTreeNode {
 60     public:
 61         LL val;
 62         LL lazy;
 63         SegTreeNode *l, *r;
 64         
 65         SegTreeNode():val(0), lazy(0), l(NULL), r(NULL) {        }
 66         
 67         inline void pushUp() {
 68             val = l->val + r->val;
 69         }
 70 }SegTreeNode;
 71 
 72 #define LIMIT 5600000
 73 SegTreeNode pool[LIMIT + 1];
 74 int top = 0;
 75 
 76 inline SegTreeNode* newnode() {
 77     if(top >= LIMIT)    return new SegTreeNode();
 78     return &pool[top++];
 79 }
 80 
 81 inline SegTreeNode* newnode(SegTreeNode*& b) {
 82     if(top >= LIMIT) {
 83         SegTreeNode* p = new SegTreeNode();
 84         *p = *b;
 85         return p;
 86     }
 87     pool[top] = *b;
 88     return &pool[top++];
 89 }
 90 
 91 typedef class DurableSegTree {
 92     public:
 93         int now, n;
 94         SegTreeNode** ls;
 95         
 96         DurableSegTree() { }
 97         DurableSegTree(int n, int limit):now(0), n(n) {
 98             ls = new SegTreeNode*[(limit + 1)];
 99             build(ls[0], 1, n);
100         } 
101         
102         void build(SegTreeNode*& node, int l, int r) {
103             node = newnode();
104             if(l == r)    return;
105             int mid = (l + r) >> 1;
106             build(node->l, l, mid);
107             build(node->r, mid + 1, r);
108         }
109         
110         void update(SegTreeNode*& old, SegTreeNode*& newo, int l, int r, int ql, int qr, LL val) {
111             newo = newnode(old);
112             if(ql > qr)    return;
113             if(ql == l && qr == r) {
114                 newo->lazy += val;
115                 newo->l = old->l, newo->r = old->r; 
116                 return;
117             }
118             int mid = (l + r) >> 1;
119             if(qr <= mid) {
120                 newo->r = old->r;
121                 update(old->l, newo->l, l, mid, ql, qr, val);
122             } else if(ql > mid){
123                 newo->l = old->l;
124                 update(old->r, newo->r, mid + 1, r, ql, qr, val);
125             } else {
126                 update(old->l, newo->l, l, mid, ql, mid, val);
127                 update(old->r, newo->r, mid + 1, r, mid + 1, qr, val);
128             }
129             newo->val += val * 1LL * (qr - ql + 1);
130         }
131         
132         inline void update(int l, int r, LL val) {
133             if(l <= r) {
134                 update(ls[now], ls[now + 1], 1, n, l, r, val);
135             } else {
136                 update(ls[now], ls[now + 1], 1, n, r + 1, l - 1, -val);
137                 ls[now + 1]->lazy += val;
138             }
139             now++;
140         } 
141         
142         void query(SegTreeNode*& node, int l, int r, int idx, LL& ret) {
143             ret += node->lazy;
144             if(l == idx && r == idx) {
145                 ret += node->val;
146                 return;
147             }
148             int mid = (l + r) >> 1;
149             if(idx <= mid)    query(node->l, l, mid, idx, ret);
150             else query(node->r, mid + 1, r, idx, ret);
151         }
152         
153         inline LL query(int k, int pos) {
154             LL ret = 0;
155             query(ls[k], 1, n, pos, ret);
156             return ret;
157         }
158 }DurableSegTree;
159 
160 int n, m, q;
161 vector<int> *owns;
162 int *goals;
163 DurableSegTree dst;
164 
165 inline void init() {
166     readInteger(n);
167     readInteger(m);
168     owns = new vector<int>[n + 1];
169     goals = new int[(n + 1)];
170     for(int i = 1, x; i <= m; i++) {
171         readInteger(x);
172         owns[x].push_back(i);
173     }
174     for(int i = 1; i <= n; i++)
175         readInteger(goals[i]);
176 
177     readInteger(q);
178     dst = DurableSegTree(m, q + 1);
179     for(int i = 1, a, b, c; i <= q; i++) {
180         readInteger(a);
181         readInteger(b);
182         readInteger(c);
183         dst.update(a, b, c);
184     }
185 }
186 
187 boolean check(int country, int mid) {
188     LL ret = 0;
189     for(int i = 0; i < (signed)owns[country].size() && ret < goals[country]; i++)
190         ret += dst.query(mid, owns[country][i]);
191     return ret >= goals[country];
192 }
193 
194 inline void solve() {
195     for(int c = 1; c <= n; c++) {
196         int l = 1, r = q;
197         while(l <= r) {
198             int mid = (l + r) >> 1;
199             if(check(c, mid))    r = mid - 1;
200             else l = mid + 1;
201         }
202         if(r == q)    puts("NIE");
203         else printf("%d\n", r + 1);
204     }
205 }
206 
207 int main() {
208 //    freopen("meteors.in", "r", stdin);
209     init();
210     solve();
211     return 0;
212 }

转载于:https://www.cnblogs.com/yyf0309/p/7190879.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据引用\[1\]中的描述,p1168问题使用了线段树解法。在构造树的过程中,需要遍历整棵树,所以时间复杂度为O(n)。但是在改变一个元素的值时,时间复杂度只有O(log(n))。求和的时候,树的节点表示一个索引范围内元素值之和,只要将区间分割对应上,平均时间复杂度是O(log(n)),最坏情况下不会超过O(n*log(n))。\[1\] 根据引用\[2\]中的描述,QUERY 5 12应该是第4、5条边的极大值。\[2\] 根据引用\[3\]中的描述,代码中的if(L<=MID)和else if(R>MID)的判断条件是为了确保查询范围在左子树或右子树中。如果加上else,会导致错误。\[3\] #### 引用[.reference_title] - *1* [leetCode307:线段树解法](https://blog.csdn.net/cyd1999/article/details/123963164)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [Spoj 375 Qtree 树链剖分 + 线段树 解法](https://blog.csdn.net/niuox/article/details/8145842)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值