CF1592

CF1592

Gamer Hemose

一定是用前两大的来打 那么将 a 排序后将 h 模上 (a[n1]+a[n]) 即可 最后剩下一点血量特判即可

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define eb emplace_back
#define ls p<<1
#define rs p<<1|1
#define mid (l+(r-l>>1))
#define pii pair<int,int>
#define lson ls,l,mid
#define rson rs,mid+1,r
#define fi first
#define se second
#define getchar() cin.get()
#define print(x) cout<<#x<<'='<<x<<endl
const int inf = 0x3f3f3f3f;
const int N = 1e3 + 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 , h , a[N];

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	int T = read();
	while ( T -- )
	{
		n = read() , h = read();
		for ( int i = 1 ; i <= n ; i ++ ) a[i] = read();
		sort ( a + 1 , a + n + 1 );
		int ans = h / ( a[n-1] + a[n] ) * 2;
		h %= ( a[n-1] + a[n] );
		if ( h == 0 ) { cout << ans << endl; continue; }
		if ( h <= a[n] ) ans += 1;
		else ans += 2;
		cout << ans << endl;
	}
	return 0;
}

Hemose Shopping

一开始想的是对于一个不降段 判断能不能给它们转开 但是 WA 了 打开题解()

如果 x2n 那么显然 我们可以任意移动两个点的位置

对于 x2>n 的情况 一定有一部分点是不能移动的 那么我们将原数组的备份排序 对于不能移动的点就跟原数组比较看是否相等即可

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define eb emplace_back
#define ls p<<1
#define rs p<<1|1
#define mid (l+(r-l>>1))
#define pii pair<int,int>
#define lson ls,l,mid
#define rson rs,mid+1,r
#define fi first
#define se second
#define getchar() cin.get()
#define print(x) cout<<#x<<'='<<x<<endl
const int inf = 0x3f3f3f3f;
const int N = 1e5 + 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 , x , a[N] , b[N];
int check ()
{
	sort ( b + 1 , b + n + 1 );
	for ( int i = 1 ; i <= n ; i ++ )
		if ( i - x < 1 && i + x > n )
			if ( a[i] != b[i] ) return 0;
	return 1;
}

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	int T = read();
	while ( T -- )
	{
		n = read() , x = read();
		for ( int i = 1 ; i <= n ; i ++ ) a[i] = b[i] = read();
		if ( x * 2 <= n ) cout << "YES" << endl;
		else cout << ( check() ? "YES" : "NO" ) << endl;
	}
	return 0;
}

Bakry and Partitioning

诈骗题

如果整个树异或起来和为 0 的话 我们任意断掉一条边都是可以的

那么如果异或起来不是 0 的而是 c 的话 那么一定是三个连通块异或起来答案为 c (每一个连通块答案都为 c ) 是最优(如果可以有更多奇数连通块 我们可以将任意两个合并并消去)

我们对于这种情况在树上进行 dfs 即可 遇到一个异或起来为 c 的联通块就剪掉 最后统计是否有大于等于三个的奇数连通块即可

注意根节点不会被统计到 要特殊统计

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define eb emplace_back
#define getchar() cin.get()
#define print(x) cout<<#x<<'='<<x<<endl
const int inf = 0x3f3f3f3f;
const int N = 1e5 + 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 a[N] , n , k , res , cnt , sum[N];

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

void dfs ( int u , int ff )
{
	sum[u] = a[u];
	for ( auto v : e[u] )
		if ( v ^ ff )
		{
			dfs ( v , u );
			if ( sum[v] == res ) ++ cnt;
			else sum[u] ^= sum[v];
		}
	if ( u == 1 && sum[u] == res ) ++ cnt;
}

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	int T = read();
	while ( T -- )
	{
		res = cnt = 0;
		n = read() , k = read();
		for ( int i = 1 ; i <= n ; i ++ ) a[i] = read() , res ^= a[i] , e[i].clear();
		for ( int i = 1 , u , v ; i < n ; i ++ ) u = read() , v = read() , add ( u , v ) , add ( v , u );
		if ( res == 0 ) cout << "YES" << endl;
		else if ( k >= 3 )
		{
			dfs(1,0);
			cout << ( cnt >= 3 && cnt & 1 ? "YES" : "NO" ) << endl;
		}
		else cout << "NO" << endl;
	}
	return 0;
}

Hemose in ICPC ?

首先 gcd 是只减不增的 那么我们相当于是询问这棵树上的最大边

看到 1e3 的点集大小和 12 次询问 不难想到需要用 logn 次询问

那么我们先用一次询问来问出最大边权是多少 然后二分出这个边的两个端点

为了保证二分的每一个点集都是一个连通块 我们考虑在欧拉序上二分 这样可以保证连通性

在交互的时候我们必须为点集去重...

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define eb emplace_back
#define mid (l+r>>1)
#define getchar() cin.get()
#define print(x) cout<<#x<<'='<<x<<endl
const int inf = 0x3f3f3f3f;
const int N = 2e3 + 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 a[N] , n , k , dfn[N] , cnt;

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

void dfs ( int u , int ff )
{
	dfn[++cnt] = u;
	for ( auto v : e[u] )
		if ( v ^ ff )
		{
			dfs ( v , u );
			dfn[++cnt] = u;
		}
}

int check ( int l , int x )
{
	set<int> s;
	for ( int i = l ; i <= x ; i ++ ) s.insert(dfn[i]);
	cout << "? " << s.size() << ' ';
	for ( auto v : s ) cout << v << ' ';
	cout << endl << flush;
	return read();
}

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	n = read();
	for ( int i = 1 , u , v ; i < n ; i ++ ) u = read() , v = read() , add ( u , v ) , add ( v , u );
	dfs ( 1 , 0 );
	int l = 1 , r = cnt;
	int res = check(l,r);
	while ( r - l > 1 )
	{
		if ( check ( l , mid ) == res ) r = mid;
		else l = mid;
	}
	cout << "! " << min ( dfn[l] , dfn[r] ) << ' ' << max ( dfn[l] , dfn[r] ) << endl << flush;
	return 0;
}

Bored Bakry

考虑什么时候我们与起来才严格大于异或:

存在一个二进制位 在这个子段中二进制表示全都是 1 且比它更高的所有二进制位全部打平(即异或起来和与起来都是 0 )

对于某一个特定的二进制位 d 由于我们需要这一段二进制都为 1 那么我们不会越过有 0 的二进制数 那么我们可以考虑在两个该位二进制为 0 的数之间进行统计

考虑为高于 d 位的二进制数记录一个 map[x]=i 表示上一个出现该状态 x 的最近位置 +1

那么我们记录一个前缀二进制状态 sum 来更新 map 如果 vis 过该状态那么统计 否则更新状态即可

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define eb emplace_back
#define mid (l+r>>1)
#define getchar() cin.get()
#define print(x) cout<<#x<<'='<<x<<endl
const int inf = 0x3f3f3f3f;
const int N = 1e6 + 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);
	n = read();
	for ( int i = 1 ; i <= n ; i ++ ) a[i] = read();
	map<int,int> pre;
	for ( int d = 0 ; d <= 20 ; d ++ )
	{
		pre.clear();
		pre[0] = 1;
		int sum = 0;
		for ( int i = 1 ; i <= n ; i ++ ) 
		{
			if ( ( a[i] & ( 1 << d ) ) == 0 )
			{
				sum = 0 , pre.clear() , pre[0] = i + 1;
				continue;
			}
			sum ^= ( a[i] >> d );
			if ( !pre.count(sum) ) pre[sum] = i + 1;   
			else ans = max ( ans , i - pre[sum] + 1 );
		}
	}
	cout << ans << endl;
	return 0;
}

Alice and Recoloring 1

较为简单的 version

考虑对于整张图进行转化 B1 W0 令每一个点的权值代表该节点本身作为左上角的 2×2 矩阵的异或奇偶性

因为顺推或者逆推都是一样的 那么我们将目标转化为让整张图的权值均变为 0

这样我们可以得出 1 操作只会修改想要的 (x,y) 节点

4 操作会修改 (n,m) (x1,y1) (x1,m) (n,y1) 这四个点的权值

不难看出 23 操作都可以被 1 操作不劣地替代 但是 4 操作可以用 3 的代价修改

但是我们可以得出 4 操作只能进行一次 否则只会用 6 的代价修改 6 个点((n,m) 被修改了两次 这样是不优的

所以我们转化并枚举整张图 如果能进行 4 操作 那么答案减一输出即可

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define eb emplace_back
#define mid (l+r>>1)
#define getchar() cin.get()
#define print(x) cout<<#x<<'='<<x<<endl
const int inf = 0x3f3f3f3f;
const int N = 500 + 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 a[N][N] , mp[N][N] , n , m , ans;

char ch;

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	n = read() , m = read();
	for ( int i = 1 ; i <= n ; i ++ )
		for ( int j = 1 ; j <= m ; j ++ ) 
			cin >> ch , mp[i][j] = ( ch == 'B' );
	for ( int i = 1 ; i <= n ; i ++ )
		for ( int j = 1 ; j <= m ; j ++ ) 
			a[i][j] = mp[i][j] ^ mp[i+1][j] ^ mp[i][j+1] ^ mp[i+1][j+1] , ans += ( a[i][j] == 1 );
	for ( int i = 1 ; i < n ; i ++ )
		for ( int j = 1 ; j < m ; j ++ )
			if ( a[i][j] && a[i][m] && a[n][j] && a[n][m] ) { cout << ans - 1 << endl; return 0; }
	cout << ans << endl;
	return 0;
}

Alice and Recoloring 2

version 1 的转化一样 但是这下 4 操作可以只用 2 的代价

那么显然 4 操作可以用 2 的代价修改三个点 (x1,y1) (x1,m) (n,y1)

那么有两个结论:

  1. 一定在上述三个点都为 1 的时候才修改

    这是因为如果有一个点不是 1 那么我们产生了一次错误的转化 最后还需要用一次 1 操作转化回来 这样和 1 操作是一样的

  2. 如果我们修改了 (x,y) 一定不会再修改 (x,y0) 同理我们也不会修改 (x0,y)

    这是因为如果这样修改 我们相当于是用了 2+2 的代价修改了 4 个点的权值 这和做四次 1 操作是一样的

那么我们做二分图匹配即可

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define eb emplace_back
#define mid (l+r>>1)
#define getchar() cin.get()
#define print(x) cout<<#x<<'='<<x<<endl
const int inf = 0x3f3f3f3f;
const int N = 1e3 + 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 a[N][N] , mp[N][N] , n , m , ans , res , vis[N] , link[N];
char ch; 

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

int hungry ( int u )
{
	for ( auto v : e[u] )
		if ( !vis[v] ) 
		{
			vis[v] = 1;
			if ( link[v] == -1 || hungry(link[v]) ) return link[v] = u , 1;
		}
	return 0;
}


signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	memset ( link , -1 , sizeof link );
	n = read() , m = read();
	for ( int i = 1 ; i <= n ; i ++ )
		for ( int j = 1 ; j <= m ; j ++ ) 
			cin >> ch , mp[i][j] = ( ch == 'B' );
	for ( int i = 1 ; i <= n ; i ++ )
		for ( int j = 1 ; j <= m ; j ++ ) 
			a[i][j] = mp[i][j] ^ mp[i+1][j] ^ mp[i][j+1] ^ mp[i+1][j+1];
	for ( int i = 1 ; i < n ; i ++ )
		for ( int j = 1 ; j < m ; j ++ )
			if ( a[i][j] && a[i][m] && a[n][j] )
				add ( i , j + n ) , add ( j + n , i );
	for ( int i = 1 ; i < n ; i ++ ) res += hungry(i) , memset ( vis , 0 , sizeof vis );
	ans -= res;
	a[n][m] ^= ( res & 1 );
	for ( int i = 1 ; i <= n ; i ++ ) 
		for ( int j = 1 ; j <= m ; j ++ )
			ans += a[i][j];
	cout << ans << endl;
	return 0;
}
posted @   Echo_Long  阅读(444)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示