Coronavirus Battle

From 2020 ECNU Campus Online Invitational Contes

题意: 给你n个三维空间的点,接下来是一波又一波的攻击,一个点能在一波攻击中存活下来,当且仅当存在一个点 \(i\), \(x_i <= x \quad and \quad y_i <= y \quad and \quad z_i <= z0\) 且至少一维是小于, 问你这些点最多能撑几波

题解:数据随机,倒是不用担心相同的情况发生。接下来就是cdq处理的经典偏序问题,但这里是最大值,不能使用经典处理,可先处理前半段,用前半段更新后半段,最后再处理后半段,用最大值树状数组进行维护。

因为要先处理前半段,中段,再后段,没了归并排序性质,倒是难以使用cdq套cdq,套一层数据结构比较合适,记得离散化第三维,以便使用数据结构。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
/*************************************************************************
> File Name: solve.cpp
> Author: liupo
> Mail: lanzongwei@gmail.com
> Created Time: 2020-05-23 15:42:16
************************************************************************/

#define GOODOJ
#define SYNC 0

#ifdef GOODOJ
#include <bits/stdc++.h>
#include <ext/pb_ds/priority_queue.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/rope>
#include <chrono>
#include <random>
using namespace __gnu_pbds;
using namespace __gnu_cxx;
#else
#include <iostream>
#include <cstdio>
#include <cmath>
#include <set>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <deque>
#include <vector>
#include <limits>
#include <cassert>
#include <sstream>
#include <iterator>
#include <functional>
#endif
using namespace std;

#define endl '\n'
#define fep(i,b,e) for(int i=(b);i<(e);++i)
#define rep(i,x) for(int i=0;i<(x);++i)
#define rap(i,x) for(auto& i : (x))
#define seg(t) (t).begin(), (t).end()
#define ep emplace_back
#define mkp make_pair
#define mkt make_tuple
#define qxx(i,x) for(int i = head[x]; ~i; i = node[i].nex)
#define F first
#define S second
#define lowbit(x) ((-(x))&(x))
#define RE register
#define getchar() getchar_unlocked()
#ifdef DEBUG
void err(istream_iterator<string>){}
template<typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args) {
cerr << *it << " = " << a << ' ';
err(++it, args...);
}
#define debug(args...) {string _s=#args;replace(seg(_s),',',' ');\
cerr<<"DEBUG:";istringstream it(_s);\
err(istream_iterator<string>(it), args);cerr<<endl;}
#else
#define debug(...)
#endif

template<typename T> inline bool cmax(T& a,const T& b) {return a<b?a=b,1:0;}
template<typename T> inline bool cmin(T& a,const T& b) {return a>b?a=b,1:0;}

#ifdef GOODOJ
mt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count());
typedef __gnu_pbds::priority_queue<int> pq;
#endif
typedef std::string str;
typedef long long ll;
typedef double db;
typedef pair<int, int> pa;
#define state(x) (1<<(x))

const double P = acos(-1.0), eps = 1e-9;
struct point { db x ,y;};
inline int sign(db a) {return a < -eps ? -1 : a > eps;}
#define dot(p1,p2,p3) ((p2.x-p1.x)*(p3.x-p1.x)+(p2.y-p1.y)*(p3.y-p1.y))
#define cross(p1,p2,p3) ((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))
#define crossOp(p1,p2,p3) sign(cross(p1,p2,p3))

const int Ma = 2e5, inf = 0x3f3f3f3f, mod = 1e9 + 7;

int ans[Ma];

struct Node {
unsigned long long x, y, z;
int* cnt;
bool operator == (const Node& b) {
return x == b.x and y == b.y and z == b.z;
}
} nd[Ma], temp[Ma];

unsigned long long k1, k2;
unsigned long long CoronavirusBeats() {
unsigned long long k3 = k1, k4 = k2; k1 = k4;
k3 ^= k3 << 23;
k2 = k3 ^ k4 ^ (k3 >> 17) ^ (k4 >> 26);
return k2 + k4;
}

int n;

void print() {
for (int i = 0; i < n; i++)
debug(nd[i].x, nd[i].y, nd[i].z, nd[i].cnt-ans);
}

void init() {
vector<unsigned long long> gz;
for (int i = 0; i < n; ++i) {
nd[i].x = CoronavirusBeats();
nd[i].y = CoronavirusBeats();
nd[i].z = CoronavirusBeats();
nd[i].cnt = ans + i;
gz.ep(nd[i].z);
}
sort(seg(gz));
gz.erase(unique(seg(gz)), gz.end());
print();
rep (i, n) nd[i].z = lower_bound(seg(gz), nd[i].z) - gz.begin();
}

struct Bit {
int bit[Ma], b[Ma], T = 0;
void add(int pos, int val) {
for (++pos; pos < Ma; pos += lowbit(pos))
bit[pos] = b[pos] < T ? val : max(bit[pos], val), b[pos] = T;
}
int sum(int pos) {
int ans = 0;
for (++pos; pos; pos -= lowbit(pos))
ans = b[pos] < T ? max(ans, 0) : max(ans, bit[pos]);
return ans;
}
int range(int l, int r) {return sum(r) - sum(l - 1);}
void clear() {++T;}
} bt;

void cdq(int l, int r) {
if (r - l <= 1) return ;
int mid(l + (r - l) / 2);
cdq(l, mid);
for (int i = l; i < r; i++) temp[i] = nd[i];
for (int i = l; i < r; i++) assert(temp[i] == nd[i]);
static auto cmp = [](Node a, Node b) {if (a.y != b.y) return a.y < b.y; else return a.z < b.z;};
sort(temp + l, temp + mid, cmp);
sort(temp + mid, temp + r, cmp);
int p = l, q = mid;
while (p < mid or q < r) {
if (q >= r or (p < mid and temp[p].y <= temp[q].y)) {
bt.add(temp[p].z, *temp[p].cnt + 1); ++p;
} else {
debug(bt.T, bt.sum(temp[q].z), temp[q].z, l, r, p, q);
cmax(*temp[q].cnt, bt.sum(temp[q].z)); ++q;
}
}
bt.clear();
cdq(mid, r);
}

signed main() {
#if SYNC==0
ios::sync_with_stdio(false);
cin.tie(0);
#endif
cin >> n >> k1 >> k2;
init(); print();
sort(nd, nd + n, [] (Node a, Node b) {if (a.x != b.x) return a.x < b.x; if (a.y != b.y) return a.y < b.y; return a.z < b.z;});
print();
cdq(0, n);
int val = *max_element(ans, ans + n);
cout << val + 1 << endl;
rep (i, n)
cout << ans[i] << " \n"[i == n - 1];

return 0;
}

Comments

2020-05-26

⬆︎TOP