Pinely Round 4 (Div. 1 + Div. 2)

题目链接:Pinely Round 4 (Div. 1 + Div. 2)

总结:被B卡了一年。

A. Maximize the Last Element

tag:模拟

Description:给定一个长度为奇数的数组,每次可以删除两个相邻的元素,直到剩下一个元素为止,求该元素的最大值。

Solution:模拟发现之后保留奇数位的值。

void solve(){
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; i ++)
cin >> a[i];
int ans = 0;
for (int i = 0; i < n; i += 2)
ans = max(ans, a[i]);
cout << ans << endl;
}

B. AND Reconstruction

tag:构造

Description:给定一个长为n1的数组b,构造一个长度为n的数组a,满足ai&ai+1==bi,否则输出1

Solution:我们令a1==b1。然后我们发现ai会影响bibi1,那么ai包含最少的1时,必须为bi1|bi。最后我们令an==bn1

Competing:一开始就想到了,但是思路不清晰,气。

void solve(){
cin >> n;
vector<int> b(n), a(n);
for (int i = 0; i < n - 1; i ++){
cin >> b[i];
}
a[0] = b[0];
for (int i = 1; i < n - 1; i ++){
a[i] = b[i] | b[i - 1];
}
a[n - 1] = b[n - 2];
for (int i = 0; i < n - 1; i ++){
if (b[i] != (a[i] & a[i + 1])){
cout << -1 << endl;
return;
}
}
for (int i = 0; i < n; i ++)
cout << a[i] << " \n"[i + 1 == n];
}

C. Absolute Zero

tag:构造

Description:给定一个长度为n的数组,每次操作可以选定一个x,将ai更新为|aix|。构造一个操作序列不操作40次,使数组a全为0.

Solution:模拟几组样例发现,如果数组中所有元素的奇偶性必须相同,否则当一个数变为奇数,另一个数会变成偶数。(开始时这两个数奇偶性不同)。

  • 我们只需要每次减去(r+l)/2,逐渐缩小上界即可。
  • 可以使用231,230,...1。逐渐缩小上界。

Competing:将r+l写为rl

void solve(){
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; i ++){
cin >> a[i];
}
sort(a.begin(), a.end());
for (int i = 1; i < n; i ++){
if ((a[i] - a[i - 1]) & 1){
cout << -1 << endl;
return;
}
}
if (a[0] == a[n - 1]){
if (a[0] == 0){
cout << 0 << endl << endl;
return;
}
cout << 1 << endl;
cout << a[0] << endl;
return;
}
vector<int> ans;
while (a[0] != a[n - 1]){
int t = (a[n - 1] + a[0]) / 2;
ans.eb(t);
for (int i = 0; i < n; i ++){
a[i] = abs(a[i] - t);
}
sort(a.begin(), a.end());
}
if (a[0] != 0)
ans.eb(a[0]);
cout << ans.size() << endl;
for (int i = 0; i < ans.size(); i ++)
cout << ans[i] << " \n"[i + 1 == ans.size()];
}

D. Prime XOR Coloring

tag:构造

四色定理:“将平面任意地细分为不相重叠的区域,每一个区域总可以用1234这四个数字之一来标记而不会使相邻的两个区域得到相同的数字。”这里所指的相邻区域是指有一整段边界是公共的。如果两个区域只相遇于一点或有限多点就不叫相邻的。

Description:有n个顶点,编号从1n,当uv为质数时,uv之间有一条边。用最少的颜色给所有顶点染色,要求相邻顶点的颜色不能相同。

Solution:考虑哪些点之间连边太难,考虑哪些点之间不连边。

  • 根据四色定理知,当n>=6时,一定需要四种颜色。
  • 考虑所有质数,发现除了2都是奇数。2的二进制013的二进制104的二进制00。那么我们对4取余,mod4相同的数异或之后一定不是质数。
  • 然后特判n<=5
void solve(){
cin >> n;
if (n == 1){
cout << 1 << endl << 1 << endl;
}
else if (n == 2){
cout << 2 << endl;
cout << 1 << " " << 2 << endl;
}
else if (n == 3){
cout << 2 << endl;
cout << "1 2 2\n";
}
else if (n == 4){
cout << 3 << endl;
cout << "1 2 2 3\n";
}
else if (n == 5){
cout << 3 << endl;
cout << "1 2 2 3 3\n";
}
else{
cout << 4 << endl;
for (int i = 1; i <= n; i ++){
cout << (i % 4) + 1 << " \n"[i == n];
}
}
}

E. Coloring Game

tag:二分图 + 交互

Description:给定一个图,一共n轮操作,每轮操作:

  • Alice选择三个颜色中选择两个颜色(1,2,3)。
  • Bob选择一个未染色的顶点进行染色。
  • 如果存在相邻顶点颜色相同Alice赢,否则Bob赢。
  • 你需要选择玩家,并给出获胜策略。

Solution:显然Alice想赢每次给出两个相同的颜色最好。模拟一下发现如果是二分图则Bob必赢,否则Alice必赢。

  • 如果不是二分图,Alice获胜,每次输出1,2即可。
  • 如果是二分图Bob获胜,先用1或者2将其中一种颜色染完,剩下的一种用3进行染色。因为1的个数加2的个数等于n,因此必定有一种颜色会被染完。
void solve(){
cin >> n >> m;
vector g(n, vector<int>());
vector st(n, -1);
for (int i = 0; i < m; i ++){
int x, y;
cin >> x >> y;
x --, y --;
g[x].eb(y);
g[y].eb(x);
}
bool flag = true;
vector<int> f1, f2;
auto dfs = [&](auto self, int x, int fa, int c) -> void {
st[x] = c;
if (c == 1){
f1.eb(x);
}
else
f2.eb(x);
for (auto i : g[x]){
if (i == fa)
continue;
if (st[i] == -1){
self(self, i, x, !c);
}
else{
if (st[i] == c){
flag = false;
}
}
}
};
dfs(dfs, 0, -1, 1);
if (flag){
cout << "Bob" << endl;
int s1 = f1.size(), s2 = f2.size();
for (int i = 0; i < n; i ++){
int a, b;
cin >> a >> b;
if (a > b)
swap(a, b);
if (a == 1){
if (s1){
s1 --;
cout << f1.back() + 1 << " " << a << endl;
f1.pop_back();
}
else{
s2 --;
cout << f2.back() + 1 << " " << b << endl;
f2.pop_back();
}
}
if (a == 2){
if (s2){
s2 --;
cout << f2.back() + 1 << " " << a << endl;
f2.pop_back();
}
else{
s1 --;
cout << f1.back() + 1 << " " << b << endl;
f1.pop_back();
}
}
}
}
else{
cout << "Alice" << endl;
for (int i = 1; i <= n; i ++){
int a, b;
cout << "1 2" << endl;
cin >> a >> b;
}
}
}

F. Triangle Formation

tag:大氛围结论 + 小范围暴力

Description:给定n根木棍,每根木棍的长度为ai。有q次询问,每次询问给定l,r。判断每次询问是否能选出6根木棍组成两个三角形。l<=i<=r,rl+1>=6,1<=ai<=109,1<=q<=105

Solution:最长的不能组成三角形的序列:斐波拉契序列,因为a1+a2==a3,那么a1+a2<=a4。我们尽可能维护前置条件。

  • 根据ai<=1e9,我们得到当F48时,最大。因此序列长度超过48时,一定能够组成三角形。我们令区间长度为60,那么当rl>=60时,一定有解。

  • 考虑rl<=60,我们先将区间内的数排序。要想三边构成三角形,那么三条边要即可能接近。如给定a,b,c,需要满足a+b<=c,假设b固定,那么a要尽可能大,c要尽快能小。因此三条边越接近越好。如果能从区间内找到两个无交集的三角形区间即符合条件。

  • 考虑连续6个数组成两个三角形,假设现在有7个数1,2,3,4,5,6,7。第一个三角形为1,6,7,那么第二个三角形为2,3,43,4,5。如果为2,3,4,那么1,6,7不如5,6,7。同理如果为3,4,5,那么1,6,7不如2,6,7

  • 假设现在有a,b,c,d,e,f六条边。其中f一定是长边,a,b一定是短边。

    • 如果c是长边,则a+b>c,d+e>f,已讨论。
    • 如果d是长边,则a+b>d,c+e>f;a+c>d,b+e>f;b+c>d,a+e>f,三种情况。
    • 如果e是长边,则a+b>e,c+d>f;a+c>e,b+d>f;a+d>e,b+c>f;b+c>e,a+d>f,四种情况。
void solve(){
int q;
cin >> n >> q;
vector<int> a(n + 1);
for (int i = 1; i <= n; i ++)
cin >> a[i];
while (q --){
int l, r;
cin >> l >> r;
if (r - l >= 60){
cout << "YES\n";
}
else{
vector<int> b;
for (int i = l; i <= r; i ++)
b.eb(a[i]);
sort(b.begin(), b.end());
int len = b.size();
int mi = -1, ma = -1;
for (int i = 1; i + 1 < len; i ++){
if (b[i - 1] + b[i] > b[i + 1]){
if (mi == -1){
mi = i;
continue;
}
ma = i;
}
}
if (ma - mi >= 3){
cout << "YES\n";
}
else{
bool ok = false;
for (int i = 0; i + 5 < len; i ++){
vector<int> c(6);
for (int j = 0; j < 6; j ++)
c[j] = b[i + j];
if (c[0] + c[1] > c[3] && c[2] + c[4] > c[5]){
ok = true;
break;
}
else if (c[0] + c[2] > c[3] && c[1] + c[4] > c[5]){
ok = true;
break;
}
else if (c[1] + c[2] > c[3] && c[0] + c[4] > c[5]){
ok = true;
break;
}
else if (c[0] + c[1] > c[4] && c[2] + c[3] > c[5]){
ok = true;
break;
}
else if (c[0] + c[2] > c[4] && c[1] + c[3] > c[5]){
ok = true;
break;
}
else if (c[0] + c[3] > c[4] && c[1] + c[2] > c[5]){
ok = true;
break;
}
else if (c[1] + c[2] > c[4] && c[0] + c[3] > c[5]){
ok = true;
break;
}
}
if (ok)
cout << "YES\n";
else
cout << "NO\n";
}
}
}
}
posted @   Sakura17  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示