CF1454

CF1454

Special Permutation

直接错开输出即可

#include <bits/stdc++.h>
using namespace std;
#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 = (1<<16) + 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;
}

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	int T = read();
	while ( T -- )
	{
		int n = read();
		for ( int i = 1 ; i < n ; i ++ ) cout << i + 1 << ' ';
		cout << 1 << endl;
	}

	return 0;
}

Unique Bid Auction

开桶模拟即可

#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 cnt[N] , a[N] , n , pos[N];

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	int T = read();
	while ( T -- )
	{
		n = read();
		memset ( pos , inf , sizeof pos );
		memset ( cnt , 0 , sizeof cnt );
		generate ( a + 1 , a + n + 1 , read );
		for ( int i = 1 ; i <= n ; i ++ ) ++ cnt[a[i]] , pos[a[i]] = min ( pos[a[i]] , i );
		int flag = 0;
		for ( int i = 1 ; i <= n ; i ++ ) if ( cnt[i] == 1 ) { flag = 1 , cout << pos[i] << endl; break; }
		if ( flag == 0 ) cout << -1 << endl;
	}
	return 0;
}

Sequence Transformation

容易发现连续的相等段是没有用的 那么我们可以先缩一下

分类讨论 设一个值 \(i\) 的出现次数 \(cnt[i]\)

  • 如果这个值 \(i\) 在头尾都出现 那么计入答案为 \(cnt[i]-1\)
  • 如果只在头或尾出现 那么计入答案为 \(cnt[i]\)
  • 否则为 \(cnt[i]+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 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 cnt[N] , a[N] , b[N] , tot , n , ans;

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	int T = read();
	while ( T -- )
	{
		memset ( cnt , 0 , sizeof cnt ) , tot = 0 , ans = inf;
		n = read();
		for ( int i = 1 ; i <= n ; i ++ ) a[i] = read();
		for ( int i = 1 ; i <= n ; i ++ ) if ( a[i] != a[i-1] ) b[++tot] = a[i] , ++ cnt[a[i]];
		for ( int i = 1 ; i <= n ; i ++ )
			if ( cnt[i] )
			{
				if ( b[1] == i && b[tot] == i ) ans = min ( ans , cnt[i] - 1 );
				else if ( b[1] == i || b[tot] == i ) ans = min ( ans , cnt[i] );
				else ans = min ( ans , cnt[i] + 1 );
			}
		cout << ans << endl;
	}
	return 0;
}

Number into Sequence

观察样例可以知道 最终答案一定形如 \(k-1\) 个相等的 \(c\) 和一个 \(n/c^{k-1}\) 其中 \(k\)\(c\) 这个因数在正整数唯一分解中的指数

输出 \(k-1\) 个是因为需要保证最后一个数有 \(c\) 这个因数

#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 = 1e5 + 5;
const int maxn = 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 , ans , cnt;
int prime[N] , isntprime[N] , tot;
void pre ()
{
	for ( int i = 2 ; i <= maxn ; i ++ )
	{
		if ( !isntprime[i] ) prime[++tot] = i;
		for ( int j = 1 ; j <= tot && i * prime[j] <= maxn ; j ++ )
		{
			isntprime[i*prime[j]] = 1;
			if ( i % prime[j] == 0 ) break;
		}
	}
}
signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	pre();
	int T = read();
	while ( T -- )
	{
		n = read() , cnt = 0 , ans = 0;
		int temp = n;
		for ( int i = 1 ; i <= tot ; i ++ )
		{
			int tmpcnt = 0;
			while ( temp % prime[i] == 0 )
			{
				temp /= prime[i];
				++ tmpcnt;
			}
			if ( cnt < tmpcnt ) ans = prime[i] , cnt = tmpcnt;
		}
		int mul = 1;
		cout << max ( cnt , 1ll ) << endl;
		for ( int i = 1 ; i < cnt ; i ++ ) cout << ans << ' ' , mul *= ans;
		cout << n / mul << endl;
	}
	return 0;
}

Number of Simple Paths

基环树的题 但是 \(*2000\)

我们想如果所有点都在环上 那么答案一定是 \(n*(n-1)\) 因为每一个有序点对存在两条简单路径

现在考虑加上树 那么对于环上的每一个点 \(s_i\) 它和它的子树内部之间的点对都是只有一条简单路径

最后答案即为 \(n*(n-1)-\sum \frac {size_{s_i}(size_{s_i}-1)} 2\)

不要用 \(memset\)\(fill\) 最好

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

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 , pos , ff , fa[N] , vis[N] , mark[N] , sz[N] , ans;

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

void dfs1 ( int u )//?
{
	vis[u] = 1;
	for ( auto v : e[u] )
	{
		if ( v == fa[u] ) continue;
		if ( vis[v] ) pos = v , ff = u;
		else fa[v] = u , dfs1(v);
	}
}

void dfs2 ( int u , int ff )
{
	sz[u] = 1;
	for ( auto v : e[u] )
	{
		if ( v == ff || mark[v] ) continue;
		dfs2 ( v , u );
		sz[u] += sz[v];
	}
}

void init()
{
	circ.clear();
	for ( int i = 1 ; i <= n ; i ++ ) e[i].clear();
	fill ( vis + 1 , vis + n + 1 , 0 );
	fill ( mark + 1 , mark + n + 1 , 0 );
	fill ( fa + 1 , fa + n + 1 , 0 );
	ans = 0;
}

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	int T = read();
	while ( T -- )
	{
		n = read();
		init();
		for ( int i = 1 , u , v ; i <= n ; i ++ ) u = read() , v = read() , add ( u , v ) , add ( v , u );
		dfs1 ( 1 );
		while ( 1 )
		{
			circ.eb(pos) , mark[pos] = 1;
			if ( pos == ff ) break;
			pos = fa[pos];
		}
		for ( auto u : circ ) dfs2 ( u , 0 ) , ans += ( sz[u] - 1 ) * sz[u] / 2;
		cout << n * ( n - 1 ) - ans << endl;
	}
	return 0;
}

Array Partition

显然看到区间最小值想到 \(st\)

但是暴力枚举两个分割点是 \(O(n^2)\) 的 考虑优化

发现我们可以先枚举出 \(x\) 端点 对于右端点 因为前缀 \(min\) 是单调不升而后缀 \(max\) 是单调不降的 那么我们二分这个位置看是否能相等即可

调了好一阵()

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

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


struct ST
{
	int maxx[N][25] , minn[N][25];
	void build ()
	{
		for ( int i = 1 ; i <= n ; i ++ ) maxx[i][0] = minn[i][0] = a[i];
		for ( int j = 1 ; j <= 20 ; j ++ )
			for ( int i = 1 ; i + ( 1 << j ) - 1 <= n ; i ++ )
				maxx[i][j] = max ( maxx[i][j-1] , maxx[i+(1<<j-1)][j-1] ) , minn[i][j] = min ( minn[i][j-1] , minn[i+(1<<j-1)][j-1] );
	}
	int qmaxx ( int l , int r )
	{
		int len = __lg(r-l+1);
		return max ( maxx[l][len] , maxx[r-(1<<len)+1][len] );
	}
	int qminn ( int l , int r )
	{
		int len = __lg(r-l+1);
		return min ( minn[l][len] , minn[r-(1<<len)+1][len] );
	}
}st;

int find ( int x , int y )
{
	int l = x , r = y;
	while ( l <= r )
	{
		int maxx = st.qmaxx ( mid + 1 , n ) , minn = st.qminn ( x , mid );
		// cout << l << ' ' << mid << ' ' << minn << endl;
		// cout << mid + 1 << ' ' << r << ' ' << maxx << endl;
		if ( aim == maxx && aim == minn ) return mid;
		if ( aim >= maxx && aim >= minn ) r = mid - 1;
		else if ( aim <= maxx && aim <= minn ) l = mid + 1;
		else break;
	}
	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] = read();
		st.build();
		int flag = 0;
		for ( int i = 1 ; i <= n ; i ++ )
		{
			aim = st.qmaxx(1,i);
			int res = find ( i + 1 , n - 1 );
			if ( res != -1 )
			{
				cout << "YES" << endl , flag = 1;
				cout << i << ' ' << res - i << ' ' << n - res << endl;
				break;
			}
		}
		if ( !flag ) cout << "NO" << endl;
	}
	return 0;
}
posted @ 2023-11-02 06:01  Echo_Long  阅读(292)  评论(0编辑  收藏  举报