正睿 25 年联赛联合训练 Day 16
正睿 25 年联赛联合训练 Day 16
得分
| T1 | T2 | T3 | 总分 | 排名 |
|---|---|---|---|---|
| \(100\) | \(100\) | \(100\) | \(300\) | \(2/17\) |
题解
T1 动物世界
枚举一下 \(A_j\),此时 \(A_i\) 可以写成 \(kA_j+r\),我们要的是 \(r\) 的最大值。那么直接暴力枚举 \(k\),然后在区间内找出最后一个出现的数算出对应的 \(r\) 即可。复杂度是 \(O(n\log^2 n)\) 的。
#include <bits/stdc++.h>
#define il inline
using namespace std;
const int Maxn = 2e5 + 5, Maxv = 1e6 + 5;
const int Inf = 2e9;
const int Mod = 1e9 + 7;
il int Add(int x, int y) {return x + y >= Mod ? x + y - Mod: x + y;} il void pls(int &x, int y) {x = Add(x, y);}
il int Del(int x, int y) {return x - y < 0 ? x - y + Mod : x - y;} il void sub(int &x, int y) {x = Del(x, y);}
il int qpow(int a, int b) {int res = 1; for(; b; a = 1ll * a * a % Mod, b >>= 1) if(b & 1) res = 1ll * res * a % Mod; return res;}
il int Inv(int a) {return qpow(a, Mod - 2);}
template <typename T> il void chkmax(T &x, T y) {x = (x >= y ? x : y);}
template <typename T> il void chkmin(T &x, T y) {x = (x <= y ? x : y);}
template <typename T>
il void read(T &x) {
x = 0; char ch = getchar(); bool flg = 0;
for(; ch < '0' || ch > '9'; ch = getchar()) flg = (ch == '-');
for(; ch >= '0' && ch <= '9'; ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48);
flg ? x = -x : 0;
}
template <typename T>
il void write(T x, bool typ = 1) {
static short Stk[50], Top = 0;
x < 0 ? putchar('-'), x = -x : 0;
do Stk[++Top] = x % 10, x /= 10; while(x);
while(Top) putchar(Stk[Top--] | 48);
typ ? putchar('\n') : putchar(' ');
}
il void IOS() {ios::sync_with_stdio(0); cin.tie(0), cout.tie(0);}
il void File() {freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout);}
bool Beg;
int n, m, a[Maxn];
int vis[Maxv], sum[Maxv];
bool End;
il void Usd() {cerr << (&Beg - &End) / 1024.0 / 1024.0 << "MB " << (double)clock() * 1000.0 / CLOCKS_PER_SEC << "ms\n"; }
int main() {
read(n);
for(int i = 1; i <= n; i++) {
read(a[i]), vis[a[i]] = 1;
chkmax(m, a[i]);
}
for(int i = 1; i <= m; i++) sum[i] = sum[i - 1] + vis[i];
int ans = 0;
for(int i = 1; i <= m; i++) {
if(!vis[i]) continue;
for(int j = i; j <= m; j += i) {
int l = j, r = min(j + i - 1, m);
int w = sum[r];
int pos = lower_bound(sum + l, sum + r + 1, w) - sum;
chkmax(ans, pos - l);
}
}
write(ans);
Usd();
return 0;
}
T2 走近科学
首先由于碰撞后立即反弹,所以我们可以直接看作没有反弹,所有车直线行驶。现在我们知道哪些位置上有车,只需要知道车的对应编号。容易发现车的编号的相对位置也是不变的,所以我们实际上就是求最后这些位置第 \(k\) 小的点。
注意到所有车的位置可以写成 \(pos_i\pm t\),那么我们直接二分最后答案,再用二分算出哪些车的位置 \(\le mid\) 即可,复杂度是 \(O(n\log^2 n)\) 的。而如果用【UR #4】元旦激光炮求第 \(k\) 大的思路来做的话可以优化到 \(O(n\log n)\),不过没必要。
#include <bits/stdc++.h>
#define il inline
#define int long long
using namespace std;
const int Maxn = 2e5 + 5;
const int Inf = 2e9 + 200;
const int Mod = 1e9 + 7;
il int Add(int x, int y) {return x + y >= Mod ? x + y - Mod: x + y;} il void pls(int &x, int y) {x = Add(x, y);}
il int Del(int x, int y) {return x - y < 0 ? x - y + Mod : x - y;} il void sub(int &x, int y) {x = Del(x, y);}
il int qpow(int a, int b) {int res = 1; for(; b; a = 1ll * a * a % Mod, b >>= 1) if(b & 1) res = 1ll * res * a % Mod; return res;}
il int Inv(int a) {return qpow(a, Mod - 2);}
template <typename T> il void chkmax(T &x, T y) {x = (x >= y ? x : y);}
template <typename T> il void chkmin(T &x, T y) {x = (x <= y ? x : y);}
il void IOS() {ios::sync_with_stdio(0); cin.tie(0), cout.tie(0);}
il void File() {freopen("data.txt", "r", stdin); freopen("out.txt", "w", stdout);}
bool Beg;
int n, q, pos[Maxn], id[Maxn], rnk[Maxn];
int v1[Maxn], v2[Maxn];
string S;
bool End;
il void Usd() {cerr << (&Beg - &End) / 1024.0 / 1024.0 << "MB " << (double)clock() * 1000.0 / CLOCKS_PER_SEC << "ms\n"; }
signed main() {
IOS();
cin >> n >> q;
for(int i = 1; i <= n; i++) cin >> pos[i], id[i] = i;
sort(id + 1, id + n + 1, [](int x, int y){return pos[x] < pos[y];});
for(int i = 1; i <= n; i++) rnk[id[i]] = i;
cin >> S; S = ' ' + S;
for(int i = 1; i <= n; i++) {
if(S[i] == 'L') v1[++v1[0]] = pos[i];
else v2[++v2[0]] = pos[i];
}
sort(v1 + 1, v1 + v1[0] + 1); sort(v2 + 1, v2 + v2[0] + 1);
while(q--) {
int x, t;
cin >> x >> t;
x = rnk[x];
int l = -Inf, r = Inf, res = 0;
while(l <= r) {
int mid = (l + r) >> 1;
int p1 = upper_bound(v1 + 1, v1 + v1[0] + 1, mid + t) - v1 - 1;
int p2 = upper_bound(v2 + 1, v2 + v2[0] + 1, mid - t) - v2 - 1;
if(p1 + p2 >= x) res = mid, r = mid - 1;
else l = mid + 1;
}
cout << abs(res) << '\n';
}
Usd();
return 0;
}
T3 自然传奇
傻逼题,诗人握持。
实际上最后的方案非常容易想到:做两次镜面反射一定可以用翻转立方体做到,所以我们只会在最后做一次镜面翻转。那么我们枚举一下正面以及正面的朝向,再枚举一下是否镜面反转,最后判断一下是否同构即可。
然后就到了傻逼的地方:枚举完上述信息后我们要重新构造出立方体的展开图,然后再判断同构。这个需要一个大模拟来实现,写起来比较恶心。这道题本身放到 T3 思维量不够,纯靠这个恶心你。
代码实现的非常丑:
#include <bits/stdc++.h>
#define il inline
using namespace std;
const int Maxn = 2e5 + 5;
const int Inf = 2e9;
const int Mod = 1e9 + 7;
il int Add(int x, int y) {return x + y >= Mod ? x + y - Mod: x + y;} il void pls(int &x, int y) {x = Add(x, y);}
il int Del(int x, int y) {return x - y < 0 ? x - y + Mod : x - y;} il void sub(int &x, int y) {x = Del(x, y);}
il int qpow(int a, int b) {int res = 1; for(; b; a = 1ll * a * a % Mod, b >>= 1) if(b & 1) res = 1ll * res * a % Mod; return res;}
il int Inv(int a) {return qpow(a, Mod - 2);}
template <typename T> il void chkmax(T &x, T y) {x = (x >= y ? x : y);}
template <typename T> il void chkmin(T &x, T y) {x = (x <= y ? x : y);}
il void IOS() {ios::sync_with_stdio(0); cin.tie(0), cout.tie(0);}
il void File() {freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout);}
bool Beg;
struct Face {
int p[3][3];
Face() {p[1][1] = p[1][2] = p[2][1] = p[2][2] = 0;}
};
struct Cube {
Face p[7];
Cube() {for(int i = 1; i <= 6; i++) p[i].p[1][1] = p[i].p[1][2] = p[i].p[2][1] = p[i].p[2][2] = 0;}
}a, b;
void input(Cube &x) { //输入
string s;
cin >> s; x.p[1].p[1][1] = s[0] - '0', x.p[1].p[1][2] = s[1] - '0';
cin >> s; x.p[1].p[2][1] = s[0] - '0', x.p[1].p[2][2] = s[1] - '0';
cin >> s; x.p[2].p[1][1] = s[0] - '0', x.p[2].p[1][2] = s[1] - '0', x.p[3].p[1][1] = s[2] - '0', x.p[3].p[1][2] = s[3] - '0', x.p[5].p[1][1] = s[4] - '0', x.p[5].p[1][2] = s[5] - '0';
cin >> s; x.p[2].p[2][1] = s[0] - '0', x.p[2].p[2][2] = s[1] - '0', x.p[3].p[2][1] = s[2] - '0', x.p[3].p[2][2] = s[3] - '0', x.p[5].p[2][1] = s[4] - '0', x.p[5].p[2][2] = s[5] - '0';
cin >> s; x.p[6].p[1][1] = s[0] - '0', x.p[6].p[1][2] = s[1] - '0';
cin >> s; x.p[6].p[2][1] = s[0] - '0', x.p[6].p[2][2] = s[1] - '0';
cin >> s; x.p[4].p[1][1] = s[0] - '0', x.p[4].p[1][2] = s[1] - '0';
cin >> s; x.p[4].p[2][1] = s[0] - '0', x.p[4].p[2][2] = s[1] - '0';
}
Face spin(Face x, int typ) { //逆时针旋转 typ*90 deg
Face res = x, tmp = x;
for(int i = 1; i <= typ; i++) {
res.p[1][1] = tmp.p[1][2];
res.p[1][2] = tmp.p[2][2];
res.p[2][1] = tmp.p[1][1];
res.p[2][2] = tmp.p[2][1];
tmp = res;
}
return res;
}
Cube rebuild(Cube x, int p) {//以 p 面为中心重构展开图
Cube res;
switch(p) {
case 1: {
res.p[1] = x.p[4];
res.p[2] = spin(x.p[2], 3);
res.p[3] = x.p[1];
res.p[4] = x.p[6];
res.p[5] = spin(x.p[5], 1);
res.p[6] = x.p[3];
break;
}
case 2: {
res.p[1] = spin(x.p[1], 1);
res.p[2] = spin(x.p[4], 2);
res.p[3] = x.p[2];
res.p[4] = spin(x.p[5], 2);
res.p[5] = x.p[3];
res.p[6] = spin(x.p[6], 3);
break;
}
case 3: {
res = x;
break;
}
}
return res;
}
Cube Spin(Cube x, int typ) { //逆时针旋转正方体 typ*90 deg
Cube res = x, tmp = x;
for(int i = 1; i <= typ; i++) {
res.p[1] = spin(tmp.p[5], 1);
res.p[2] = spin(tmp.p[1], 1);
res.p[3] = spin(tmp.p[3], 1);
res.p[4] = spin(tmp.p[4], 3);
res.p[5] = spin(tmp.p[6], 1);
res.p[6] = spin(tmp.p[2], 1);
tmp = res;
}
return res;
}
Cube Rebuild(Cube x, int p) {//以 p 面为中心重构展开图
switch(p) {
case 1: {
return rebuild(x, 1);
break;
}
case 2: {
return rebuild(x, 2);
break;
}
case 3: {
return rebuild(x, 3);
break;
}
case 4: {
Cube res = rebuild(x, 2);
return rebuild(res, 2);
break;
}
case 5: {
Cube res = rebuild(x, 2);
res = rebuild(res, 2);
return rebuild(res, 2);
break;
}
case 6: {
Cube res = Spin(x, 2);
return rebuild(res, 1);
break;
}
}
}
Face mirror(Face x) { //镜像平面
Face res;
res.p[1][1] = x.p[1][2], res.p[1][2] = x.p[1][1];
res.p[2][1] = x.p[2][2], res.p[2][2] = x.p[2][1];
return res;
}
Cube Mirror(Cube x) { //镜像对称
Cube res;
res.p[1] = mirror(x.p[1]), res.p[3] = mirror(x.p[3]), res.p[6] = mirror(x.p[6]), res.p[4] = mirror(x.p[4]);
res.p[2] = mirror(x.p[5]), res.p[5] = mirror(x.p[2]);
return res;
}
int vis[7][7], num[7];
bool Check(Cube a, Cube b) {
for(int i = 1; i <= 6; i++) {
num[i] = 0;
for(int j = 1; j <= 6; j++) vis[i][j] = 0;
}
for(int i = 1; i <= 6; i++) {
for(int j = 1; j <= 2; j++) {
for(int k = 1; k <= 2; k++) {
int p = a.p[i].p[j][k], q = b.p[i].p[j][k];
vis[p][q] = 1;
}
}
}
for(int i = 1; i <= 6; i++) {
int pos = 0, cnt = 0;
for(int j = 1; j <= 6; j++) {
if(vis[i][j] == 1) pos = j, cnt++;
}
if(cnt != 1) return 0;
num[pos]++;
}
for(int i = 1; i <= 6; i++) if(num[i] != 1) return 0;
return 1;
}
int T;
void solve() {
input(a), input(b);
bool flg = 0;
for(int i = 1; i <= 6; i++) { //正面
for(int j = 0; j <= 3; j++) { //旋转
for(int k = 0; k <= 1; k++) { //镜像
Cube res = Rebuild(a, i);
res = Spin(res, j);
if(k) res = Mirror(res);
if(Check(res, b)) flg = 1;
}
}
}
cout << (flg ? "yes" : "no") << '\n';
}
bool End;
il void Usd() {cerr << (&Beg - &End) / 1024.0 / 1024.0 << "MB " << (double)clock() * 1000.0 / CLOCKS_PER_SEC << "ms\n"; }
int main() {
IOS();
cin >> T;
while(T--) solve();
Usd();
return 0;
}

浙公网安备 33010602011771号