CF1635

CF1635

Min Or Sum

手推样例可以发现 每一组的答案即为每一组的二进制数或起来

粗浅证明:对于一组数 xi,yi 最优操作一定是将这两个数变成 xi|yi,0 那么这样进行到最后 就会有 n10 和最后剩下的一个 a1|a2||an 输出即可

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define eb emplace_back
#define pii pair<int,int>
#define fi first
#define se second
#define getchar() cin.get()
const int N = 2e5 + 5;
int read()
{
	int f = 1 , x = 0;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f;
}


int n , a[N] , ans;

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	int T = read();
	while ( T -- )
	{
		n = read() , ans = 0;
		generate ( a + 1 , a + n + 1 , read );
		for_each ( a + 1 , a + n + 1 , [&](int sum) { ans |= sum; } );
		cout << ans << endl;
	}
	return 0;
}

Avoid Local Maximums

B 题应该并不是很难的 dp 那么考虑贪心从前往后扫一遍

我们每次操作一定可以消除一个局部最大值(直接将序列削平即可) 考虑每次操作是否可能更优

对于一个局部最大值 ai 我们为了消除这个最大值 可以将后一个值 ai+1 改成 max(ai,ai+2)

这样我们不仅可以消除 ai 同时也有一定概率将 ai+2 改为非局部最大值 是最优的情况

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define eb emplace_back
#define pii pair<int,int>
#define fi first
#define se second
#define getchar() cin.get()
const int N = 2e5 + 5;

int read()
{
	int f = 1 , x = 0;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f;
}


int n , a[N] , ans;

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	int T = read();
	while ( T -- )
	{
		n = read() , ans = 0;
		generate ( a + 1 , a + n + 1 , read );
		for ( int i = 2 ; i <= n - 1 ; i ++ )
			if ( a[i] > a[i-1] && a[i] > a[i+1] ) ans ++ , a[i+1] = max ( a[i] , a[i+2] ); 
		cout << ans << endl;
		for_each ( a + 1 , a + n + 1 , [](const int &v) { cout << v << ' '; } );
		cout << endl;
	}
	return 0;
}

Differential Sorting

首先判断简单情况:

  1. 如果 an1>an 那么无解 因为无法找到合法的操作使得 an1 减小
  2. 如果原序列不降 那么直接判断并输出即可

想到这儿就说明一定 an1an 考虑这两个数怎么使用

  • 如果 an0 那么一定可以通过将前面所有数全部修改为 an1an 来实现
  • 否则一定无解 证明: 目标序列一定全为负数 设我们用了 m 步操作达到了目标状态 最后一步操作为 ax,ay,az 那么一定有 ayazaxayaz 移项得 axayaz 因为 az 为正数 那么 ax 一定大于 ay 得到矛盾
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define eb emplace_back
#define pii pair<int,int>
#define fi first
#define se second
#define getchar() cin.get()
const int N = 2e5 + 5;

int read()
{
	int f = 1 , x = 0;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f;
}


int n , a[N] , ans;

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	int T = read();
	while ( T -- )
	{
		n = read();
		generate ( a + 1 , a + n + 1 , read );
		int flag = 1;
		for ( int i = 1 ; i < n ; i ++ ) if ( a[i] > a[i+1] ) { flag = 0; break; }
		if ( flag == 1 ) { cout << 0 << endl; continue; }
		if ( a[n-1] > a[n] || a[n] < 0 ) { cout << -1 << endl; continue; }
		cout << n - 2 << endl;
		for ( int i = 1 ; i <= n - 2 ; i ++ ) cout << i << ' ' << n - 1 << ' ' << n << endl;
	}
	return 0;
}

Infinite Set

极好的思维题

对于题目中的操作 2x+1 可以在二进制下等效为在末尾添加一个 14x 相当于是在末尾添加两个 0

那么我们设置 f[i] 代表在末尾添加 i 位的方案数 那么显然有 f[0]=f[1]=1f[i]=f[i1]+f[i2] 那么我们为 f 数组做前缀和即可

显然 对于一个 ai 计入答案即为 sum[pgetbit(a[i])]

其中 getbit 函数为该二进制的的最高位 1 的位置(也就是该二进制数的有效位数)

但是这样会重复计算 所以我们对于每一个 ai 进行标记并对于每一个 ai 向前跳状态 如果前置状态被标记了 那么就说明这个数可以被舍弃

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define eb emplace_back
#define pii pair<int,int>
#define fi first
#define se second
#define getchar() cin.get()
#define int long long 
const int N = 2e5 + 5;
const int mod = 1e9 + 7;

int read()
{
	int f = 1 , x = 0;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f;
}


int n , p , a[N] , ans , f[N] , sum[N];

map<int,int> mp;

int check ( int x )
{
	while ( x )
	{
		if ( x & 1 ) x >>= 1;
		else if ( x % 4 == 0 ) x >>= 2;
		else break;
		if ( mp.count(x) ) return 0;
	}
	return 1;
}

int getbit ( int x )
{
	for ( int i = 30 ; i >= 0 ; i -- )
		if ( x & ( 1 << i ) ) return i + 1;
}

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	n = read() , p = read();
	generate ( a + 1 , a + n + 1 , read );
	for_each ( a + 1 , a + n + 1 , [&](const int v) { mp[v] = 1; } );
	f[1] = 1 , f[2] = 2;
	for ( int i = 3 ; i <= p ; i ++ ) ( f[i] = f[i-1] + f[i-2] ) %= mod;
	sum[0] = 1;
	for ( int i = 1 ; i <= p ; i ++ ) ( sum[i] = sum[i-1] + f[i] ) %= mod;
	for ( int i = 1 ; i <= n ; i ++ ) if ( check(a[i]) && getbit(a[i]) <= p ) ( ans += sum[p-getbit(a[i])] ) %= mod;
	cout << ans << endl;
	return 0;
}

Cars

偏套路的图论题

我们显然可以发现性质:无关紧要和命中注定的点对都是方向相反的 那么我们可以据此建立二分图染色来确定每一个点的方向

这里用 col=1 表示向左 col=2 表示向右 dfs 染色并判断无解

在确定每一个点的方向之后 考虑赋值坐标

对于每一组 op=1 的点对 说明 col=1 的点需要在左面 那么从 col=1 的点向 col=2 的点连边表示小于的关系

op=2 同理

最后跑拓扑排序并为每一个点在出队的时候赋值即可

如果最后 idxn 那么说明有点没有覆盖到 判断无解即可

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define eb emplace_back
#define pii pair<int,int>
#define fi first
#define se second
#define getchar() cin.get()
const int N = 2e5 + 5;

int read()
{
	int f = 1 , x = 0;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f;
}

int n , m , vis[N] , col[N] , flag = 1 , idx , in[N] , ans[N];

queue <int> q;

vector<int> e[N];
inl void add ( int u , int v ) { e[u].eb(v); }

struct node { int op , u , v; } a[N];

void dfs ( int u , int c )//c=1朝左 c=2朝右
{
	// cout << u << ' ' << c << endl;
	col[u] = c , vis[u] = 1;
	for ( auto v : e[u] )
	{
		if ( col[v] == c ) flag = 0;
		if ( vis[v] ) continue;//这里是continue而不是return
		dfs ( v , 3 - c );
	}
}

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	n = read() , m = read();
	for ( int i = 1 ; i <= m ; i ++ ) a[i].op = read() , a[i].u = read() , a[i].v = read() , add ( a[i].u , a[i].v ) , add ( a[i].v , a[i].u );
	for ( int i = 1 ; i <= n ; i ++ ) if ( !vis[i] ) dfs ( i , 1 );
	if ( !flag ) return cout << "NO" << endl , 0;
	for ( int i = 1 ; i <= n ; i ++ ) e[i].clear();
	for ( int i = 1 ; i <= m ; i ++ )
	{
		int u = a[i].u , v = a[i].v;
		if ( a[i].op == 1 )
		{
			if ( col[u] == 1 ) add ( u , v ) , ++ in[v];
			else add ( v , u ) , ++ in[u];
		}
		else 
		{
			if ( col[u] == 2 ) add ( u , v ) , ++ in[v];
			else add ( v , u ) , ++ in[u];
		}
	}
	for ( int i = 1 ; i <= n ; i ++ ) if ( !in[i] ) q.push(i);
	while ( !q.empty () )
	{
		int u = q.front(); q.pop();
		ans[u] = ++ idx;
		for ( auto v : e[u] ) if ( ! --in[v] ) q.push(v); 
	}
	if ( idx != n ) return cout << "NO" << endl , 0;
	cout << "YES" << endl;
	for ( int i = 1 ; i <= n ; i ++ ) cout << ( col[i] == 1 ? 'L' : 'R' ) << ' ' << ans[i] << endl;
	return 0;
}
posted @   Echo_Long  阅读(593)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示