2019.10.11考試解題報告


2019.10.11考試解題報告

總結

期望得分:\(100 + 100 + 0\)
實際得分:\(100 +96 + 0\)(原因是\(T2\)滿分\(96\))

期望得分與實際得分一致,也算是沒寫掛了
但是在時間的安排上不是很合理,在\(T1\)上花了很長時間,因為發現自己的線段樹\(so\)慢,之后導致去做\(T3\)的時候時間已經不多了
以后還是要合理安排時間


思路

T1

題意:
一個長度為\(n\)的數組,有\(q\)次操作,操作包括三種
分別是單點加,單點修改與整體修改,每次操作之后都要輸出數組中所有元素的和。

打了個線段樹發現有點慢……裸的線段樹根本不行,甚至會\(MLE\)
而且讀入還是有點慢……
然后驚人地發現不用線段樹就可以……

發現答案不難統計,所以每次進行簡單的調整就可以了
用一個數組\(b\)表示每個位置的層數
定義\(sjp\)代表最最先進的那一層(就是當前層。。)

每次3操作都讓\(sjp++\),並將\(now\)賦值為\(y\)
如果進行\(1、2\)操作時層數不是\(sjp\),就把\(x\)這個位置的值賦為\(now\)
並把\(b[x]\)賦值為\(sjp\),表示當前\(x\)這個位置的層數已經是\(sjp\)了……
這樣一次次更新就行了

T2

題意:
給你一張\(n\)個點\(m\)條邊,且邊權全為正的有向圖,求這張圖的最長路,並保證存在最長路

20分

可以試下神奇的最短路算法\(floyd\)
時間復雜度\(O(n^3)\),可以過前\(20\%\)

40分

可以試下\(N\)遍堆優化\(dijkstra\)或者\(SPFA\)(關於\(SPFA\),他死了)

100分

既然保證最長路存在,並且邊權全為正,就表明了這張圖是個有向無環圖(\(DAG\)),所以我們就可以用拓撲排序 + \(DP\)來解決

T3

題意:
給你一張\(n\)個點\(m\)條邊的無向圖,求圖上與每個點最短距離之和最小與最大的兩個點,點可以在邊上任意位置,問這兩個點與每個點最短距離之和是多少。(可以不為整數)

考場上來不及做,也不會做的一道神題

老師下發的題解上說這是一道真正考察選手綜合算法能力的題目

但我不會,菜死了


代碼

T1

死慢死慢的線段樹

//知識點:真·線段樹 
/*
By:Loceaner
*/
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

inline int read() {
	char c = getchar();
	int x = 0, f = 1;
	for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
	for( ; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
	return x * f;
}

const int N = 1e7 + 11;

#define lson rt << 1
#define rson rt << 1 | 1

struct node {
	int l, r, sum, lazy; 
} t[N << 2];

long long ans = 0;

inline void pushup(int rt) {
	t[rt].sum = t[lson].sum + t[rson].sum;
}

void build(int l, int r, int rt) {
	t[rt].l = l, t[rt].r = r;
	if(l == r) return;
	int mid = (l + r) >> 1;
	build(l, mid, lson);
	build(mid + 1, r, rson);
}

void bian(int mb, int x, int rt) {//變! 
	if(t[rt].l == mb && t[rt].r == mb) {
		t[rt].sum = x;
		return;
	}
	int mid = (t[rt].l + t[rt].r) >> 1;
	if(mb <= mid) bian(mb, x, lson);
	else bian(mb, x, rson);
	pushup(rt);
}

void jia(int mb, int x, int rt) {//加! 
	if(t[rt].l == mb && t[rt].r == mb) {
		t[rt].sum += x;
		return;
	}
	int mid = (t[rt].l + t[rt].r) >> 1;
	if(mb <= mid) jia(mb, x, lson);
	else jia(mb, x, rson);
	pushup(rt);
}

void update(int L, int R, int x, int rt) {
	if(t[rt].l == t[rt].r) {
		t[rt].sum = x;
		return;
	}
	int mid = (t[rt].l + t[rt].r) >> 1;
	if(mid >= R)  update(L, R, x, lson);
    else if(L > mid)  update(L, R, x, rson);
    else {
        update(L, mid, x, lson);
        update(mid + 1, R, x, rson);
    }
	pushup(rt);
}

void find(int L, int R, int rt) {
	if(t[rt].l == L && t[rt].r == L){
        ans += t[rt].sum;
        return;
    }
    int mid = (t[rt].l + t[rt].r) >> 1;
    if(mid >= R)  find(L, R, lson);
    else if(L > mid)  find(L, R, rson);
    else {
        find(L, mid, lson);
        find(mid + 1, R, rson);
    }
    pushup(rt);
}

int n, q;

int main() {
	freopen("segmenttree.in", "r", stdin);
	freopen("segmenttree.out", "w", stdout);
	n = read(), q = read();
	build(1, n, 1);
	while(q--) {
		int opt = read(), x, y;
		if(opt == 1) {
			x = read(), y = read();
			bian(x, y, 1);
		}
		else if(opt == 2) {
			x = read(), y = read();
			jia(x, y, 1);
		}
		else if(opt == 3) {
			y = read();
			update(1, n, y, 1);
		}
		ans = 0;
		find(1, n, 1);
		cout << ans << '\n';
	}
	return 0;
}

玄學的\(O(q)\)滿分做法

/*
By:Loceaner 
*/
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

const int MAXSIZE=50000020; 
const int N = 1e7 + 11;

int bufpos;
char buf[MAXSIZE];

int re() { 
    int val = 0;
    for(; buf[bufpos] < '0' || buf[bufpos] > '9'; bufpos ++);
    for(; buf[bufpos] >= '0' && buf[bufpos] <= '9'; bufpos ++)
        val = val * 10 + buf[bufpos] - '0';
    return val;
}

int n, q, a[N], now, b[N], sjp;
ll sum = 0;

int main(){
	freopen("segmenttree.in", "r", stdin);
	freopen("segmenttree.out", "w", stdout);
	buf[fread(buf, 1, MAXSIZE, stdin)] = '\0';
    bufpos = 0;
    n = re(); q = re();
    for(int i = 1; i <= q; i ++){
    	int opt = re();
    	if(opt == 1){
    		int x = re(), y = re();
    		if(b[x] < sjp) a[x] = now, b[x] = sjp;
			//a[x] = y;
			sum += y - a[x];
			a[x] = y;
			cout << sum << '\n';
		}
		if(opt == 2){
    		int x = re(), y = re();
    		if(b[x] < sjp) a[x] = now, b[x] = sjp;
			sum += y;
			a[x] += y;
			cout << sum << '\n';
		}
		if(opt == 3){
    		int y = re();
    		now = y;
    		sjp++;
			sum = y * n;
			cout << sum << '\n';
		}
	}
	return 0;
}

T2

考場滿分代碼

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

typedef long long ll;
const int MAXSIZE=50000020; //讀入緩存大小,不要改動 
const int N = 1e6 + 11;

int bufpos;
char buf[MAXSIZE];

int re(){ //讀入一個int類型的整數 
    int val = 0;
    for(; buf[bufpos] < '0' || buf[bufpos] > '9'; bufpos ++);
    for(; buf[bufpos] >= '0' && buf[bufpos] <= '9'; bufpos ++)
        val = val * 10 + buf[bufpos] - '0';
    return val;
}

struct node {
	int to, nxt, val;
} e[N << 1];

int n, m;
int head[N], tot;
ll f[N], ans;

inline void add(int from, int to, int val) {
	e[++tot].val = val;
	e[tot].to = to;
	e[tot].nxt = head[from];
	head[from] = tot;
}

queue <int> q;
int ind[N], seq[N], cnt;

signed main(){
	freopen("lpsa.in", "r", stdin);
	freopen("lpsa.out", "w", stdout);
	buf[fread(buf, 1, MAXSIZE, stdin)] = '\0';
    bufpos = 0;
    n = re(); m = re();
    for(int i = 1; i <= m; i ++){
    	int u = re(), v = re(), w = re();
		add(v, u, w);
		ind[u]++;
	}
	for(int i = 1; i <= n; i++) if(!ind[i]) q.push(i);
	while(!q.empty()) {
		int u = q.front();
		q.pop();
		seq[++cnt] = u;
		for(int i = head[u]; i; i = e[i].nxt) {
			int v = e[i].to;
			--ind[v];
			if(ind[v] == 0) q.push(v);
		} 
	}
	for(int i = 1; i <= cnt; i++) {
		int now = seq[i];
		for(int j = head[now]; j; j = e[j].nxt) {
			int to = e[j].to;
			f[to] = max(f[to], f[now] + e[j].val);
		}
		ans = max(f[now], ans);
	}
	cout << ans << '\n';
	return 0;
}

T3

考場代碼沒臉放

神奇的正解

#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
#include <map>
#include <complex>

#define lc k << 1
#define rc k << 1 | 1

#define inf 0x3f3f3f3f
 
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;

struct edge{
	int to, nxt;
	ll w;
}e[100005];

int h[1005], cnt;

void addedge(int x, int y, ll w){
	cnt++; e[cnt].to = y; e[cnt].w = w; e[cnt].nxt = h[x]; h[x] = cnt;
	cnt++; e[cnt].to = x; e[cnt].w = w; e[cnt].nxt = h[y]; h[y] = cnt;
}

int n, m;
ll dis[1005][1005]; int vis[1005];
ll sum[1005];
void spfa(int s){
	memset(vis, 0, sizeof(vis));
	queue<int> q; dis[s][s] = 0; vis[s] = 1; q.push(s);
	while(!q.empty()){
		int x = q.front(); q.pop();
		for(int i = h[x]; i; i = e[i].nxt){
			if(dis[s][e[i].to] > dis[s][x] + e[i].w){
				dis[s][e[i].to] = dis[s][x] + e[i].w;
				if(!vis[e[i].to]) vis[e[i].to] = 1, q.push(e[i].to);
			}
		}
		vis[x] = 0;
	}
}

double mn = 1e17, mx = 0;
double st[1005];
void sol(int x, int y, ll w){
	double res = sum[x];
	for(int i = 1; i <= n; i ++){
		st[i] = 1.0 * (dis[y][i] - dis[x][i] + w) / 2.0;
	}
	sort(st + 1, st + n + 1);
	double d = 0, tmp; ll k = n;
	for(int i = 1; i <= n; i ++){
		tmp = st[i] - d;
		res = res + tmp * k;
		d = st[i]; k -= 2;
		mn = min(mn, res);
		mx = max(mx, res);
	}
}

int main(){
	freopen("foodshop.in", "r", stdin);
	freopen("foodshop.out", "w", stdout);
	
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= n; i ++){
		for(int j = 1; j <= n; j ++) dis[i][j] = 1e17;
	}
	for(int i = 1; i <= m; i ++){
		int x, y; ll w;
		scanf("%d%d%lld", &x, &y, &w);
		addedge(x, y, w);
	}
	for(int i = 1; i <= n; i ++){
		spfa(i);
	}
	for(int i = 1; i <= n; i ++){
		for(int j = 1; j <= n; j ++){
			sum[i] += dis[i][j];
		}
		mn = min(mn, (double)sum[i]);
		mx = max(mx, (double)sum[i]);
	}
	for(int x = 1; x <= n; x ++){
		for(int i = h[x]; i; i = e[i].nxt){
			sol(x, e[i].to, e[i].w);
		}
	}
	printf("%.1lf %.1lf\n", mn, mx);
	return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM