CF1343

Candies

相当于是 \((1<<k)-1=\frac{n}{x}\) 那么我们枚举合法的 \(k\) 即可

#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
#define int unsigned int
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 , ans;


signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	int T = read();
	while ( T -- )
	{
		n = read() , ans = 0; 
		for ( int k = 4 ; k - 1 <= n ; k <<= 1 )
			if ( n % ( k - 1 ) == 0 ) { ans = n / ( k - 1 ); break; }
		cout << ans << endl;
	}	
	return 0;
}

Balanced Array

如果长度 \(mod\ 4\neq 0\) 那么无解 因为此时左右的奇偶性一定不相同

显然我们可以暴力将 \(1-n\) 中的奇偶数填进去 对于最后一个奇数特判一下就好

#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
#define int unsigned int
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 , ans;


signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	int T = read();
	while ( T -- )
	{
		n = read();
		if ( n % 4 == 0 && n >= 4 )
		{
			cout << "YES" << endl;
			for ( int i = 1 ; i <= n / 2 ; i ++ )
				cout << i * 2 << ' ';
			for ( int i = 1 ; i < n / 2 ; i ++ )
				cout << i * 2 - 1 << ' ';
			cout << n - 1 + n / 2 << endl;
		}
		else cout << "NO" << endl;
	}
	return 0;
}

Alternating Subsequence

一开始看成了连续的子序列 导致过不去样例()

因为我们需要最长 所以我们对于每一个正负相同的连续段 都需要选取最大的一个数 累加即可

#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
#define int long long 
const int N = 2e5 + 5;
const int inf = 0x3f3f3f3f3f3f3f3f;

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];

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	int T = read();
	while ( T -- )
	{
		n = read();
		int sum = 0 , maxx = -inf , op = -1;
		for ( int i = 1 ; i <= n ; i ++ )
		{
			a[i] = read();
			if ( op == -1 ) 
			{
				maxx = max ( maxx , a[i] );
				op = ( a[i] > 0 );
			}
			else if ( op == 0 )
			{
				if ( a[i] < 0 ) maxx = max ( maxx , a[i] );
				else sum += maxx , op = 1 , maxx = a[i];
			}
			else 
			{
				if ( a[i] > 0 ) maxx = max ( maxx , a[i] );
				else sum += maxx , op = 0 , maxx = a[i];
			}
		}
		cout << sum + ( maxx == -inf ? 0 : maxx ) << endl;
	}
	return 0;
}

Constant Palindrome Sum

显然我们有 \(O(nk)\) 的暴力 即枚举最终的目标状态并判断是否能达到

考虑优化 设 \(swap0[i]\)\(swap1[i]\)\(swap2[i]\) 分别表示目标为 \(i\) 的时候 需要改 \(0/1/2\) 次的点对个数

\(0\) 次非常显然 直接枚举所有点对并标记即可

\(1\) 次 我们可以修改上面的定义 即 \(swap1[i]\) 表示至多修改一次的代价 直接将 \(min(a[i],a[n-i+1])+1\)\(max(a[i],a[n-i+1])+k\) 之间的所有点标记 \(+1\) 即可 这个可以用差分数组实现

对于 \(2\) 次 即为 \(swap2[i]=\frac n 2 -swap1[i]\)

最后计入答案即为 \(swap2[i] \times 2 + swap1[i] - swap0[i]\)

\(O(nk)\):

#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 N = 2e5 + 5;
const int inf = 0x3f3f3f3f;

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 , k , a[N] , ans;

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	int T = read();
	while ( T -- )
	{
		ans = inf;
		n = read() , k = read();
		for ( int i = 1 ; i <= n ; i ++ ) a[i] = read();
		for ( int aim = 1 ; aim <= k * 2 ; aim ++ )
		{
			int res = 0;
			for ( int i = 1 ; i <= n / 2 ; i ++ )
			{
				if ( a[i] + a[n-i+1] == aim ) res += 0;
				else if ( ! ( a[i] + 1 <= aim && aim <= a[i] + k || a[n-i+1] + 1 <= aim && aim <= a[n-i+1] + k ) ) res += 2;
				else ++ res;
			}
			ans = min ( res , ans );
		}
		cout << ans << endl;
	}
	return 0;
}

\(O(n)\) 正解:

#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 N = 2e5 + 5;
const int inf = 0x3f3f3f3f;

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 , k , a[N] , ans , swap0[N] , swap1[N] , swap2[N];

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	int T = read();
	while ( T -- )
	{
		ans = inf;
		n = read() , k = read();
		fill ( swap0 + 1 , swap0 + 2 * k + 1 , 0 );
		fill ( swap1 + 1 , swap1 + 2 * k + 1 , 0 );
		fill ( swap0 + 1 , swap2 + 2 * k + 1 , 0 );
		for ( int i = 1 ; i <= n ; i ++ ) a[i] = read();
		for ( int i = 1 ; i <= n / 2 ; i ++ ) ++ swap0[a[i]+a[n-i+1]];
		for ( int i = 1 ; i <= n / 2 ; i ++ ) swap1[min(a[i],a[n-i+1])+1] ++ , swap1[max(a[i],a[n-i+1])+k+1] --;
		for ( int i = 1 ; i <= 2 * k ; i ++ ) swap1[i] += swap1[i-1];
		for ( int i = 1 ; i <= 2 * k ; i ++ ) swap2[i] = n / 2 - swap1[i] , ans = min ( ans , swap1[i] - swap0[i] + swap2[i] * 2 );
		cout << ans << endl;
	}
	return 0;
}

Weights Distributing

对于两个点 \(a,b\) 显然有一个贪心:我们求出 \(a,b\) 之间的最短路 并将所有最小的边贪心地填进去

但是这样对于三个点是不成立的:因为我们有可能出现 \(a,b\) 的最短路和 \(b,c\) 的最短路重复的情况

那么我们考虑答案路径: \(a\rightarrow i\rightarrow b\rightarrow i\rightarrow c\) 那么我们枚举中间的 \(i\) 节点 进行起点为 \(a,b,c\) 的三次 \(bfs\) 并组合答案即可

#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
#define int long long
const int N = 4e5 + 5;
const int inf = 0x3f3f3f3f3f3f3f3f;

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 , w[N] , dis[3][N] , sum[N] , a , b , c , vis[N] , ans;

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

void bfs ( int s , int op )
{
	fill ( vis + 1 , vis + n + 1 , 0 );
	queue<int> q; q.push(s) , vis[s] = 1;
	while ( !q.empty() ) 
	{
		int u = q.front(); q.pop();
		for ( auto v : e[u] ) if ( !vis[v] ) dis[op][v] = dis[op][u] + 1 , vis[v] = 1 , q.push(v);
	}
}

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	int T = read();
	while ( T -- )
	{
		ans = inf;
		n = read() , m = read() , a = read() , b = read() , c = read();
		for ( int i = 1 ; i <= n ; i ++ ) e[i].clear();
		for ( int i = 0 ; i <= 2 ; i ++ ) for ( int j = 1 ; j <= n ; j ++ ) dis[i][j] = 0;	
		generate ( w + 1 , w + m + 1 , read );
		sort ( w + 1 , w + m + 1 );
		partial_sum ( w + 1 , w + m + 1 , sum + 1 );
		for ( int i = 1 , u , v ; i <= m ; i ++ ) u = read() , v = read() , add ( u , v ) , add ( v , u );
		bfs ( a , 0 ) , bfs ( b , 1 ) , bfs ( c , 2 );
		for ( int i = 1 ; i <= n ; i ++ ) if ( dis[0][i] + dis[1][i] + dis[2][i] <= m ) ans = min ( ans , sum[dis[0][i] + dis[1][i] + dis[2][i]] + sum[dis[1][i]] );
		cout << ans << endl;
	}
	return 0;
}

Restore the Permutation by Sorted Segments

很奇妙的构造

我们可以先枚举第一位填什么 然后向后枚举所有限制 看能否满足

对于我们枚举的每一位 我们都枚举所有的限制和限制中的每一位数 如果这条限制只剩这一个数且这条限制其他的数位置都在区间内 那么是合法的 填写进去

否则直接开始枚举第一位的下一个数即可

#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 N = 2e2 + 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 , ans[N] , pos[N] , a[N][N];

int pd ()
{
	for ( int i = 2 ; i <= n ; i ++ )//枚举每一位
	{
		for ( int j = 1 ; j < n ; j ++ ) 
		{
			int lim = a[j][0] , x = -1;
			for ( int k = 1 ; k <= a[j][0] ; k ++ )
			{
				int now = a[j][k];
				if ( !pos[now] ) x = now;
				else if ( pos[now] >= i - a[j][0] + 1 ) lim --;
			}
			if ( lim == 1 && x != -1 )
			{
				ans[i] = x , pos[x] = i;
				break;
			}
		}
		if ( !ans[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();
		for ( int i = 1 ; i < n ; i ++ )
		{
			a[i][0] = read();
			for ( int j = 1 ; j <= a[i][0] ; j ++ ) a[i][j] = read();
		}
		for ( int i = 1 ; i <= n ; i ++ )
		{
			for ( int j = 1 ; j <= n ; j ++ ) ans[j] = pos[j] = 0;
			ans[1] = i , pos[i] = 1;
			if ( pd() ) break;
		}
		for ( int i = 1 ; i <= n ; i ++ ) cout << ans[i] << ' ';
		cout << endl;
	}
	return 0;
}

posted @ 2023-10-28 16:25  Echo_Long  阅读(363)  评论(0编辑  收藏  举报