Problem F Greedy Sequence

题目链接:https://nanti.jisuanke.com/t/41303

题意: 给出n个整数,构造s1,s2,s3…sns1,s2,s3…sn,sisi满足五个条件

  1. s1[i]=i
  2. 对于1<j<=n,si[j]<si[j−1];
  3. 对于任意的si[j]在a串中的位置pos[j],满足∣pos[j]−pos[j−1]∣<=k,且si中的每一个数字只能a中出现一次;
  4. 如果选择的si长度小于n,其余位置就填0;
  5. 尽量使bi足够大(能得到的最大字典序);

思路: 这题数据真的水,线段树都不用,直接暴力,从i到n,找第i之前出现的符合条件最大的数,答案是找到的数的结果+1。

Accepted Code:

/* 
 * @Author: lzyws739307453 
 * @Language: C++ 
 */
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
int ans[MAXN], pos[MAXN];
int main() {
	int t, n, k, x;
	scanf("%d", &t);
	while (t--) {
		scanf("%d%d", &n, &k);
		memset(ans, 0, sizeof(ans));
		for (int i = 1; i <= n; i++) {
			scanf("%d", &x);
			pos[x] = i;
		}
		ans[1] = 1;
		printf("%d", ans[1]);
		for (int i = 2; i <= n; i++) {
			ans[i] = 1;
			for (int j = i - 1; j >= 1; j--) {
				if (abs(pos[j] - pos[i]) <= k) {
					ans[i] = ans[j] + 1;
					break;
				}
			}
			printf(" %d", ans[i]);
		}
		printf("\n");
	}
	return 0;
}

Problem H Holy Grail

题目链接:https://nanti.jisuanke.com/t/41305

题意: 给你n个点,m条边的图,边的权值有正有负。并且原图没有重边和负环,现在给你6个顶点和终点,让你添加6条边,并且要保证添加后图无负环,输出添加的每条边的最小值。
思路: 因为要添加一个边,并且要求无负环,所以要加上一个反向的相反权值,正好将它抵消。Spfa纪录起点终点间的最短距离,然后给他们添加一条边,权值是反向最短距离取负值。

Accepted Code:

/* 
 * @Author: lzyws739307453 
 * @Language: C++ 
 */
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 305;
const int MAXM = 510;
struct edge {
	int u, v, w;
	edge() {}
	edge(int u, int v, int w) : u(u), v(v), w(w) {}
}e[MAXM];
bool vis[MAXN];
int dis[MAXN], f[MAXN], cnt, n;
void Add(int u, int v, int w) {
	e[++cnt] = edge(f[u], v, w);
	f[u] = cnt;
}
void init() {
	memset(dis, 0x3f, sizeof(dis));
	memset(vis, false, sizeof(vis));
}
void Spfa(int s) {
	init();
	queue <int> Q;
	Q.push(s);
	dis[s] = 0;
	vis[s] = true;
	while (!Q.empty()) {
		int u = Q.front();
		Q.pop();
		vis[u] = false;
		for (int i = f[u]; ~i; i = e[i].u) {
			int v = e[i].v;
			if (dis[v] > dis[u] + e[i].w) {
				dis[v] = dis[u] + e[i].w;
				if (!vis[v]) {
					vis[v] = true;
					Q.push(v);
				}
			}
		}
	}
}
int main() {
	int t, m;
	scanf("%d", &t);
	while (t--) {
		cnt = 0;
		scanf("%d%d", &n, &m);
		memset(f, -1, sizeof(f));
		for (int i = 0; i < m; i++) {
			int u, v, w;
			scanf("%d%d%d", &u, &v, &w);
			Add(u, v, w);
		}
		int q = 6;
		while (q--) {
			int u, v;
			scanf("%d%d", &u, &v);
			Spfa(v);
			Add(u, v, -dis[u]);
			printf("%d\n", -dis[u]);
		}
	}
	return 0;
}