AtCoder ARC 125 部分题解

A - Dial Up

找到最近的与第一个位置不同的数字的位置,第一次转换需要这个距离的代价,之后的转换只需要 \(1\) 的代价左右切换即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn = 200010;
const int INF = 1000000007;

int n, m;
int a[maxn], b[maxn];

ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }

int main(){
	n = read(), m = read();
	
	int l = INF, r = INF;
	for(int i = 1 ; i <= n ; ++i) {
		a[i] = read();
		if(i > 1 && a[i] != a[1]) r = min(r, i-1);
	}
	for(int i = 1 ; i <= m ; ++i) b[i] = read();
	
	for(int i = n ; i >= 2 ; --i) if(a[i] != a[1]){
		l = n-i+1; break;
	}

	int cur = a[1], ans = 0, flag = 0;
	
	for(int i = 1 ; i <= m ; ++i){
		if(cur != b[i]){
			ans += (flag == 0) ? min(l, r) : 1;
			cur ^= 1;
			flag = 1;
		}
		++ans;
	}
	
	if(ans >= INF) printf("-1\n");
	else printf("%d\n", ans);
	
	return 0;
}

B - Squares

注意移项后可以变成平方差公式,分解后变为 \((x+t)(x-t)=y\),令 \(p=(x+t),q=(x-t)\),则原问题转化成计数 \((p,q)\) 对的数量,满足

  • \(q <= p\)
  • \(\frac{p+q}{2}=x\)
  • \(pq \leq n\)
  • \(q \equiv p \bmod 2\)
  • \(q \leq p \leq \frac{n}{q}\)
    枚举 \(q\) 即可,\(q\) 不超过 \(\sqrt n\)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int M = 998244353; 

ll n;

ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }

int main(){
	n = read();
	int ans = 0;
	for(int i = 1 ; i <= (int)sqrt(n+0.5) ; ++i){
		ll l = i, r = n / i;
		if((r-l+1)&1) {
			ll len = (r-l)/2;
			ans = (ans + len % M + 1) % M;
		} else{
			ll len = (r-l+1)/2;
			ans = (ans + len % M) % M;
		} 
	}
	printf("%d\n", ans);
	return 0;
}

C - LIS to Original Sequence

题意:

给定一个排列,给定其中的一个最长上升子序列,求满足条件的字典序最小的排列

题解:

如果要求最长上升子序列长度为 \(k\),则序列中一定有 \(k\) 个连续的的下降段,这样保证同一下降段中的数不会形成上升序列,不同下降段中的数形成上升序列,且长度为 \(k\),贪心构造即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn = 200010;
const int INF = 1000000007;

int n, k;
int a[maxn]; 
int vis[maxn];

ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }

int main(){
	n = read(), k = read();
	for(int i = 1 ; i <= k ; ++i) a[i] = read(), vis[a[i]] = 1;
	
	int cur = 1;
	while(vis[cur]) ++cur;
	for(int i = 1 ; i < k ; ++i){
		printf("%d ", a[i]);
		if(cur < a[i]) {
			printf("%d ", cur);
			cur++;
			while(vis[cur]) ++cur;	
		}
	}
	for(int i = n ; i > max(a[k], cur) ; --i){
		if(!vis[i]) printf("%d ", i);
	}
	printf("%d ", a[k]);
	for(int i = a[k]-1 ; i >= cur ; --i){
		if(!vis[i]) printf("%d ", i);
	} printf("\n");
	return 0;
}

D - Unique Subsequence

题意:

给定一个序列,求有多少个子序列在该序列中只出现一次

题解:

\(dp[i]\) 表示第 \(i\) 个元素必选,序列前 \(i\) 个元素中,子序列只出现一次的数量,则若 \(f[i]\) 能转移到 \(f[j]\),要满足 \((i,j)\) 区间中不出现 \(a[i],a[j]\),否则生成的子序列不唯一

所以 \(f[i]\) 统计的答案即为 \((pre[i],i-1)\) 中不含 \(a[j]\)\(f[j]\) 之和,可以使用树状数组维护,只维护当前每个值最后一个位置的 \(f\),因为每个值只有最后一个位置会对答案产生贡献,统计答案只统计每个值最后一个位置的 \(f\)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn = 200010;
const int INF = 1000000007;

int n, k;
int a[maxn]; 
int vis[maxn];

ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }

int main(){
	n = read(), k = read();
	for(int i = 1 ; i <= k ; ++i) a[i] = read(), vis[a[i]] = 1;
	
	int cur = 1;
	while(vis[cur]) ++cur;
	for(int i = 1 ; i < k ; ++i){
		printf("%d ", a[i]);
		if(cur < a[i]) {
			printf("%d ", cur);
			cur++;
			while(vis[cur]) ++cur;	
		}
	}
	for(int i = n ; i > max(a[k], cur) ; --i){
		if(!vis[i]) printf("%d ", i);
	}
	printf("%d ", a[k]);
	for(int i = a[k]-1 ; i >= cur ; --i){
		if(!vis[i]) printf("%d ", i);
	} printf("\n");
	return 0;
}
posted @ 2021-09-12 10:32  Tartarus_li  阅读(79)  评论(0编辑  收藏  举报