ABC 409

A:水
B:注意考虑清楚有多种情况,注意不是让你在A数组里找元素而是在1-N里找!!!
C:注意L一定要是3的倍数否则必不可能有等边三角形

#include<iostream>
#include<cstdio>
#include<queue>
#include<stack>
#include<cstring>
#include<algorithm>
#include <sstream>
#include <vector>
#include <queue>
using namespace std;

const int MAXN = 500005;
int N, D, R,fk,L,fg,pg1,pg2;
long long ans;
long long OL[MAXN];
bool cmp(int a, int b) {
	return a > b;
}
int main() {
	int tp = 0;
	fk = 0;
	OL[fk] = 1;
	scanf("%d %d", &N,&L);
	for(int i=1;i<N;i++){
		scanf("%d",&tp);
		fk = (fk + tp)%L;
		OL[fk]++;	
	}
	if(L%3!=0)
	{
		cout<<"0\n";
		return 0;
	}
	ans = 0;
	pg1 = L/3;
	pg2 = pg1*2;
	for(int i=0;i<pg1;i++){
		if(OL[i]&&OL[i+pg1]&&OL[i+pg2]){
			ans += OL[i] * OL[i+pg1] * OL[i+pg2];	
		}
	}
	printf("%lld",ans);
	return 0;
}

D:要求你执行一次把任意字母移动到后面任意位置使得总字典序最小,自然从第一位开始尝试能否往后移,而只要当前字母大于等于后面字母就可以往后移,第一个可以往后移的即是答案。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int MAXN = 200005;
char S[MAXN], tmp[MAXN], ans[MAXN];
int T, N,fk;

int main() {
	scanf("%d", &T);
	while(T--) {
		scanf("%d",&N);
		scanf("%s", S);
		int gg = 0;fk = 0; 
		for(int i = 1;i < N;i++){
			if(S[gg] < S[i]){
				gg = i;
			}else if(S[gg] > S[i]){
				fk = i;
				while(S[gg] >= S[fk]){
					fk++;
					if(fk == N){
						break;
					}
				}
				break;
			}
		}
		for(int i=0;i<N;i++){
			if(i>=gg && i<fk - 1){
				printf("%c",S[i+1]);
			}else if(i == fk - 1){
				printf("%c",S[gg]);
			}else{
				printf("%c",S[i]);
			}
		}
		printf("\n");
	}
	return 0;
}
/*
3
5
snuke
7
atcoder
1
x
 */

E:采用后序遍历,对于叶节点来说,其归零电荷的方法只有转移电子进来或出去到父节点,而这代价是一样的,所以干脆直接给出到父节点即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int MAXN = 100005;  // 树的最大节点数
int N;
int x[MAXN];
long long total_energy;

struct Edge {
	int to;
	int weight;
};

Edge edges[MAXN*2];  // 双向边
int head[MAXN], next_edge[MAXN*2], edge_count;

// 添加边
void add_edge(int u, int v, int w) {
	edge_count++;
	edges[edge_count] = {v, w};
	next_edge[edge_count] = head[u];
	head[u] = edge_count;
}

// 后序遍历计算每个子树的电荷总和,并累加边的贡献
void dfs(int u, int parent) {
	for (int i = head[u]; i != -1; i = next_edge[i]) {
		Edge& e = edges[i];
		int v = e.to;
		int w = e.weight;
		if (v == parent) continue;
		
		dfs(v, u);
		int charge = abs(x[v]);
		total_energy += (long long)charge * w;
		x[u] += x[v];
	}
}

int main() {
	int u, v, w;
	memset(head, -1, sizeof(head));
	edge_count = 0;
	total_energy = 0;
	
	scanf("%d", &N);
	
	// 读取每个顶点的电荷
	for (int i = 1; i <= N; i++) {
		scanf("%d", &x[i]);
	}
	
	// 读取树的边
	for (int j = 1; j < N; j++) {
		scanf("%d%d%d", &u, &v, &w);
		add_edge(u, v, w);
		add_edge(v, u, w);
	}
	
	// 从顶点1开始DFS
	dfs(1, -1);
	
	printf("%lld\n", total_energy);
	
	return 0;
}
posted @ 2025-06-11 15:33  Thomastine  阅读(4)  评论(0)    收藏  举报