zoukankan      html  css  js  c++  java
  • 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 << '
    ';
    	}
    	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)] = '';
        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 << '
    ';
    		}
    		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 << '
    ';
    		}
    		if(opt == 3){
        		int y = re();
        		now = y;
        		sjp++;
    			sum = y * n;
    			cout << sum << '
    ';
    		}
    	}
    	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)] = '';
        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 << '
    ';
    	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
    ", mn, mx);
    	return 0;
    }
    
  • 相关阅读:
    【转】Pandas学习笔记(七)plot画图
    【转】Pandas学习笔记(六)合并 merge
    【转】Pandas学习笔记(五)合并 concat
    【转】Pandas学习笔记(四)处理丢失值
    【转】Pandas学习笔记(三)修改&添加值
    【转】Pandas学习笔记(二)选择数据
    17秋 SDN课程 第二次上机作业
    17秋 SDN课程 第三次上机作业
    17秋 SDN课程 第一次上机作业
    Ubuntu 14.04 安装sublime
  • 原文地址:https://www.cnblogs.com/loceaner/p/11654235.html
Copyright © 2011-2022 走看看