题解 Codeforces Round #811 (Div. 3)

本文详细介绍了Codeforces Round #811 (Div. 3)的比赛题目,包括A到G七道题目。重点讨论了如何解决各个题目,涉及深度优先搜索、图论、算法等多个方面。
摘要由CSDN通过智能技术生成

Codeforces Round #811 (Div. 3)

比赛链接

SolvedTimePenalty
7/7122min390

A. Everyone Loves to Sleep

注意可能会出现跨到第二天的情况。

#define multiple_test_cases

const int N = 15;
int n, H, M, h[N], m[N];
int ans;

void solve(){
	n = rdi;
	H = rdi;
	M = rdi;
	ans = 0x3f3f3f3f;
	for(int i = 1; i <= n; ++ i){
		h[i] = rdi;
		m[i] = rdi;
		if(h[i] > H || (h[i] == H && m[i] >= M)){
			ans = min(ans, (h[i]-H)*60+m[i]-M);
		}
		h[i] += 24;
		if(h[i] > H || (h[i] == H && m[i] >= M)){
			ans = min(ans, (h[i]-H)*60+m[i]-M);
		}
	}
	write(ans/60);
	writen(ans%60);
}

B. Remove Prefix

从右往左遍历,记录每一个数出现的次数。

#define multiple_test_cases

const int N = 2e5 + 10;
int n, a[N], cnt[N];

void solve(){
	n = rdi;
	for(int i = 1; i <= n; ++ i){
		a[i] = rdi;
	}
	for(int i = n; i; -- i){
		if(cnt[a[i]]){
			writen(i);
			for(int j = 1; j <= n; ++ j){
				cnt[j] = 0;
			}
			return;
		}
		++ cnt[a[i]];
	}
	writen(0);
	for(int j = 1; j <= n; ++ j){
		cnt[j] = 0;
	}
	return;
}

C. Minimum Varied Number

显然答案类似于 x56789

#define multiple_test_cases

int n, ans[10];

void solve(){
	n = rdi;
	for(int i = 9; i >= 0; -- i){
		if(n >= i){
			ans[i] = i;
			n -= i;
			if(n == 0){
				for(int j = i; j <= 9; ++ j){
					putchar(ans[j] + '0');
				}
				endl;
				return;
			}
		} else {
			ans[i] = n;
			for(int j = i; j <= 9; ++ j){
				putchar(ans[j] + '0');
			}
			endl;
			return;
		}
	}
	puts("123456789");
}

D. Color with Occurrences

???

暴力。枚举第 i i i 位与第 j j j 个串的第 x x x 位对应是否能匹配。

#define multiple_test_cases

const int N = 100;
int n, res[N][2], tot;
char t[N], s[15][15];

bool cmp(int x, int i, int j){
	int k = strlen(s[i]+1);
	for(int p = 1; p <= k; ++ p){
		if(s[i][p] != t[x-j+p]){
			return false;
		}
	}
	return true;
}

void solve(){
	scanf("%s", t+1);
	int l = strlen(t+1);
	n = rdi;
	for(int i = 1; i <= n; ++ i){
		scanf("%s", s[i] + 1);
	}
	int ans = 0;
	for(int i = 1; i <= l;){
		int mx = 0, pi = 0, pj = 0;
		for(int j = 1; j <= n; ++ j){
			int k = strlen(s[j]+1);
			for(int x = 1; x <= k; ++ x){
				if(cmp(i, j, x)){
					if(mx < k-x+1){
						mx = k-x+1;
						pi = j;
						pj = x;
					}
				}
			}
		}
		if(!mx){
			puts("-1");
			return;
		}
		++ ans;
		int k = strlen(s[pi]+1);
        res[ans][0] = pi;
        res[ans][1] = i - (pj-1);
		i = i + k-pj+1;
	}
	writen(ans);
	for(int i = 1; i <= ans; ++ i){
        write(res[i][0]);
        write(res[i][1]);
        endl;
    }
}

E. Add Modulo 10

考虑每种个位:

  • 1 , 2 , 4 , 8 , 16 , . . . 1,2,4,8,16,... 1,2,4,8,16,...
  • 2 , 4 , 8 , 16 , . . . 2,4,8,16,... 2,4,8,16,...
  • 3 , 6 , . . . 3,6,... 3,6,...
  • 4 , 8 , 16 , . . . 4,8,16,... 4,8,16,...
  • 5 , 10 , 10 , . . . 5,10,10,... 5,10,10,...
  • 6 , 12 , 14 , 18 , 26 , . . . 6,12,14,18,26,... 6,12,14,18,26,...
  • 7 , 14 , 18 , 26 , . . . 7,14,18,26,... 7,14,18,26,...
  • 8 , 16 , . . . 8,16,... 8,16,...
  • 9 , 18 , 26 , . . . 9,18,26,... 9,18,26,...
  • 0 , 0 , . . . 0,0,... 0,0,...

所以我们可以把所有数按个位以及十位的奇偶性分为三组:

  1. 十位为奇数,个位为 1 , 2 , 4 , 8 1,2,4,8 1,2,4,8;十位为偶数,个位为 3 , 6 , 7 , 9 3,6,7,9 3,6,7,9
  2. 十位为偶数,个位为 1 , 2 , 4 , 8 1,2,4,8 1,2,4,8;十位为奇数,个位为 3 , 6 , 7 , 9 3,6,7,9 3,6,7,9
  3. 个位为 0 , 5 0,5 0,5

如果原序列中所有数不全位于同一组,则无解,否则:

  • 若所有数都位于前两组其中一组,有解。
  • 若所有数位于第三组,则判断序列中最小值和最大值,如果相差 ≤ 5 \leq5 5 且最大值个位为 0 0 0,有解。否则无解。(因为个位为 0 0 0 就变不了了)
#define multiple_test_cases

const int N = 2e5 + 10;
int n, a[N];

void solve(){
	n = rdi;
	bool flg = false;
	int cnt1 = 0, cnt2 = 0;
	for(int i = 1; i <= n; ++ i){
		a[i] = rdi;
		if(a[i]%10 == 5 || a[i]%10 == 0){
			flg = true;
		}
		int tmp = a[i]%10;
		if(tmp == 1 || tmp == 2 || tmp == 4 || tmp == 8){
			if((a[i]/10) % 2){
				++ cnt1;
			} else {
				++ cnt2;
			}
		}
		if(tmp == 3 || tmp == 6 || tmp == 7 || tmp == 9){
			if((a[i]/10) % 2){
				++ cnt2;
			} else {
				++ cnt1;
			}
		}
	}
	if(flg){
		int mn = a[1], mx = a[1];
		for(int i = 2; i <= n; ++ i){
			if(a[i]%5){
				puts("NO");
				return;
			}
			mn = min(mn, a[i]);
			mx = max(mx, a[i]);
		}
		if(mx == mn || (mx == mn + 5 && mx%10 == 0)){
			puts("YES");
		} else {
			puts("NO");
		}
	} else {
		if(cnt1 && cnt2){
			puts("NO");
		} else {
			puts("YES");
		}
	}
}

F. Build a Tree and That Is It

全场最难题。

如果有解, 1 − 2 , 2 − 3 , 3 − 1 1-2,2-3,3-1 12,23,31 三条路径只有如下四种情况:

接下来具体考虑:

  • d 12 , d 23 , d 31 d_{12},d_{23},d_{31} d12,d23,d31 其一大于另两数之和,无解。
  • 可以发现四种解中每条路径都在 d 12 , d 23 , d 31 d_{12},d_{23},d_{31} d12,d23,d31 中出现两次,所以若 d 12 + d 23 + d 31 d_{12}+d_{23}+d_{31} d12+d23+d31 为奇数,无解。
  • d 12 + d 23 + d 31 > 2 n − 2 d_{12}+d_{23}+d_{31} > 2n-2 d12+d23+d31>2n2,无解。
  • d 12 , d 23 , d 31 d_{12},d_{23},d_{31} d12,d23,d31 其一等于另两数之和,分情况构造左上、左下、右上三种情况。

否则设 1 , 2 , 3 1,2,3 1,2,3 到中间节点 x x x 的三条路径长度分别为 x , y , z x,y,z x,y,z,可以列出方程组:

{ x + y = d 12 y + z = d 23 z + x = d 31 \begin{cases}x+y=d_{12}\\y+z=d_{23}\\z+x=d_{31}\end{cases} x+y=d12y+z=d23z+x=d31

解得

{ x = ( d 12 − d 23 + d 31 ) ÷ 2 y = ( d 23 − d 31 + d 12 ) ÷ 2 z = ( d 31 − d 12 + d 23 ) ÷ 2 \begin{cases}x=(d_{12}-d_{23}+d_{31})\div2\\y=(d_{23}-d_{31}+d_{12})\div2\\z=(d_{31}-d_{12}+d_{23})\div2\end{cases} x=(d12d23+d31)÷2y=(d23d31+d12)÷2z=(d31d12+d23)÷2

此时如果 x , y , z x,y,z x,y,z 中不全是整数,无解。否则按照右下图构造即可。

考场代码,很丑。

#define multiple_test_cases

const int N = 2e5 + 10;
int n, d12, d23, d31, fa[N];

void build(int x, int l, int r, int xl, int xr){
	stack<int> st;
	st.push(x);
	int tmp = 4;
	for(int i = 1; i < xl; ++ i){
		st.push(tmp);
		++ tmp;
	}
	st.push(l);
	while(!st.empty()){
		int x = st.top();
		st.pop();
		if(!st.empty()) fa[x] = st.top();
	}
	st.push(x);
	for(int i = 1; i < xr; ++ i){
		st.push(tmp);
		++ tmp;
	}
	st.push(r);
	while(!st.empty()){
		int x = st.top();
		st.pop();
		if(!st.empty()) fa[x] = st.top();
	}
	for(int i = tmp; i <= n; ++ i){
		fa[i] = 1;
	}
}
void buildd(int x, int y, int z){
	stack<int> st;
	st.push(4);
	int tmp = 5;
	for(int i = 1; i < x; ++ i){
		st.push(tmp);
		++ tmp;
	}
	st.push(1);
	while(!st.empty()){
		int ww = st.top();
		st.pop();
		if(!st.empty()) fa[ww] = st.top();
	}
	st.push(4);
	for(int i = 1; i < y; ++ i){
		st.push(tmp);
		++ tmp;
	}
	st.push(2);
	while(!st.empty()){
		int ww = st.top();
		st.pop();
		if(!st.empty()) fa[ww] = st.top();
	}
	st.push(4);
	for(int i = 1; i < z; ++ i){
		st.push(tmp);
		++ tmp;
	}
	st.push(3);
	while(!st.empty()){
		int ww = st.top();
		st.pop();
		if(!st.empty()) fa[ww] = st.top();
	}
	for(int i = tmp; i <= n; ++ i){
		fa[i] = 1;
	}
}

void solve(){
	n = rdi;
	d12 = rdi;
	d23 = rdi;
	d31 = rdi;
	if((d12 + d23 + d31) & 1){
		puts("NO");
	} else if((d12 + d23 + d31) > n+n-2){
		puts("NO");
	} else {
		if(d12 == d23 + d31){
			build(3, 1, 2, d31, d23);
		} else if(d23 == d12 + d31){
			build(1, 2, 3, d12, d31);
		} else if(d31 == d12 + d23){
			build(2, 1, 3, d12, d23);
		} else {
			int x = d12 - d23 + d31;
            int y = d23 - d31 + d12;
            int z = d31 - d12 + d23;
            if((x&1) || (y&1) || (z&1) || x<0 || y<0 || z<0){
                puts("NO");
                return;
            } else {
                x >>= 1;
                y >>= 1;
                z >>= 1;
                buildd(x, y, z);
            }
		}
        puts("YES");
		for(int i = 1; i <= n; ++ i){
			if(fa[i]){
				write(i);
				writen(fa[i]);
                fa[i] = 0;
			}
		}
	}
}

G. Path Prefixes

dfs,设 d i s i dis_i disi 表示 1 − i 1-i 1i 路径上的 a a a 和。用一个栈记录 1 − i 1-i 1i 路径上每个点到 1 1 1 路径上的 b b b 和。每遍历到一个节点 x x x,在栈中跑二分,找出最大的 ≤ a x \leq a_x ax 的值。

#define multiple_test_cases

const int N = 2e5 + 10;
struct edge{
	ll a, b;
};
vector<pair<int, edge> > G[N];
ll st[N];
int n, ans[N];
ll dis[N];

void dfs(int x, int fa, int dep){
	for(int i = 0; i < G[x].size(); ++ i){
		int y = G[x][i].first;
		int a = G[x][i].second.a;
		int b = G[x][i].second.b;
		if(y == fa){
			continue;
		}
		dis[y] = dis[x] + a;
		st[dep+1] = st[dep] + b;
		int l = 0, r = dep+1;
		while(l < r){
			int mid = l + r + 1 >> 1;
			if(st[mid] <= dis[y]){
				l = mid;
			} else {
				r = mid - 1;
			}
		}
		ans[y] = l;
		dfs(y, x, dep+1);
	}
}

void solve(){
	n = rdi;
	for(int i = 2; i <= n; ++ i){
		int p = rdi;
		int a = rdll;
		int b = rdll;
		G[p].push_back(make_pair(i, (edge){ a,b }));
	}
	dfs(1, 0, 0);
	for(int i = 2; i <= n; ++ i){
		write(ans[i]);
	}
    endl;
    for(int i = 1; i <= n; ++ i){
        st[i] = ans[i] = dis[i] = 0;
        G[i].clear();
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Codeforces Round 894 (Div. 3) 是一个Codeforces举办的比赛,是第894轮的Div. 3级别比赛。它包含了一系列题目,其中包括题目E. Kolya and Movie Theatre。 根据题目描述,E. Kolya and Movie Theatre问题要求我们给定两个字符串,通过三种操作来让字符串a等于字符串b。这三种操作分别为:交换a中相同位置的字符、交换a中对称位置的字符、交换b中对称位置的字符。我们需要先进行一次预处理,替换a中的字符,然后进行上述三种操作,最终得到a等于b的结果。我们需要计算预处理操作的次数。 根据引用的讨论,当且仅当b[i]==b[n-i-1]时,如果a[i]!=a[n-i-1],需要进行一次操作;否则不需要操作。所以我们可以遍历字符串b的前半部分,判断对应位置的字符是否与后半部分对称,并统计需要进行操作的次数。 以上就是Codeforces Round 894 (Div. 3)的简要说明和题目E. Kolya and Movie Theatre的要求。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [Codeforces Round #498 (Div. 3) (A+B+C+D+E+F)](https://blog.csdn.net/qq_46030630/article/details/108804114)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [Codeforces Round 894 (Div. 3)A~E题解](https://blog.csdn.net/gyeolhada/article/details/132491891)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值