正睿 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;
}
posted @ 2025-04-11 14:39  UKE_Automation  阅读(33)  评论(0)    收藏  举报