• 2019.10.15考试解题报告


    2019.10.15考试解题报告

    总结

    期望得分:(30 + 30 + 0)
    实际得分:(30 + 0 + 0)

    炸了,这次考试完全炸了,(T1)只会打暴力,(T2)神奇大(DP)(T3)概率期望迷

    (T1)想不出(70)分来,只能默默(orz cgp)大佬

    (T2)打错了……(awsl)

    (T3)是个鬼……(毒)不懂


    思路

    T1

    先打(30)分暴力,这个很好打

    然后(70)(O(nlog^2))怎么写呢

    考虑二分答案

    二分的左端点为(0),右端点为整整两个序列中的最大值(maxn)(len)先计算出取出的区间长度的中间值,然后进行二分,用(upper\_bound)计算出(A)序列中在(mid)左边的数的个数(now1),以及(B)序列中在(mid)左边的数的个数(now2),若他们两个的长度大于(len)就缩小范围到(mid)左边,相应的缩小(r1)(r2)的范围,反之则缩小范围到(mid)右边,相应扩大(l1)(l2),最后输出(ans)就好了

    满分咋做?((from solution))

    实际上我们可以进行一波分类讨论。可以通过当前数的位置得到
    这个数在另一个序列的期望位置。假设当前的数为(x),期望位置的数为 (y),下一个数为(z),那么 (zle x le y)(x)就是答案,否则比较一下大小,往两边跳。

    这种方法要特判很多种情况。事实上,我们还有一种较为简便,
    普适性更强的方法。假设当前要取的是区间的第(k)大,将(k)折半,放在两个区间的对应位置 (s, t)上,比较 (a[s], b[t]),不妨设(a[s] < b[t]),那么答案可以化归至区间([l1, s - 1],[l2, r2])的第(frac{k}{2})大数(因为(a)序列比(a[s])小的那些数一定可以全部舍去), 递归即可

    T2

    (30)分的话,可以想到一个(n^2)(dp)方程

    (dp[i])表示分割([l,i])的最大答案,转移方程为

    [dp[i] = max_{j = 0}^{i - 1}dp[j] + f(min_{x = j + 1}^{i} a_x),dp[0] = 0 ]

    满分做法?(同样(from solution))

    显然可以采用一个单调递增的栈来维护(g_x = min_{x = j}^{i}a[x])具体地,单调栈中的元素(l_1,l_2,…l_m)表示(g_{l_i}!=g_{l_{i-1}})的每个(l_i)(就是最小值变化的转折点),那么有(forall x in [l_i, l_{i+1} -1], g(x))相同,此时(dp)值最大的那个点一定最优秀,于是维护(h_i = max_{x = l_i}^{l_i +1}dp[x]),表示每个取到最小值元素对应区间的最优答案。这样的话,每一次的答案就是(max h_i + f(g_{l_i})),采用一棵线段树或者可删除堆维护单调栈即可。

    T3

    不会,咕咕咕


    代码

    T1

    考场三十分代码

    /*
    By:Loceaner
    */
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    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 = 5e5 + 11;
    
    int n, m, a[N], b[N], now[N], cnt, tot, ans[N];
    int opt, x, y, z, l1, l2, r1, r2;
    
    void solve() {
    	while(m--) {
    		opt = read();
    		if(opt == 1) {
    			x = read(), y = read(), z = read();
    			if(x == 0) a[y] = z;
    			else b[y] = z;
    		} else {
    			l1 = read(), r1 = read(), l2 = read(), r2 = read();
    			cnt = 0;
    			while(l1 <= r1 || l2 <= r2) {
    				if(l1 <= r1 && l2 <= r2) {
    					if(a[l1] < b[l2]) now[++cnt] = a[l1++];
    					else now[++cnt] = b[l2++];
    				} else if(l1 <= r1) now[++cnt] = a[l1++];
    				else now[++cnt] = b[l2++];
    			}
    //			cout << "now: ";
    //			for(int i = 1; i <= cnt; i++) cout << now[i] << " ";
    //			cout << '
    ';
    			ans[++tot] = now[cnt / 2 + 1];
    		}
    	}
    	for(int i = 1; i < tot; i++) cout << ans[i] << '
    ';
    	cout << ans[tot];
    }
    
    int main() {
    	freopen("median.in", "r", stdin);
    	freopen("median.out", "w", stdout);
    	n = read(), m = read();
    	for(int i = 1; i <= n; i++) a[i] = read();
    	for(int i = 1; i <= n; i++) b[i] = read();
    	if(n <= 1000 && m <= 2000) return solve(), 0;
    	return 0;
    }
    
    

    跑五秒才能过的正解代码

    /*
    By:Loceaner
    */
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    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 = 5e5 + 11;
    
    int n, m, a[N], b[N], now[N], cnt, tot, ans[N];
    int opt, x, y, z, l1, l2, r1, r2;
    
    void solve() {
    	while(m--) {
    		opt = read();
    		if(opt == 1) {
    			x = read(), y = read(), z = read();
    			if(x == 0) a[y] = z;
    			else b[y] = z;
    		} else {
    			l1 = read(), r1 = read(), l2 = read(), r2 = read();
    			cnt = 0;
    			while(l1 <= r1 || l2 <= r2) {
    				if(l1 <= r1 && l2 <= r2) {
    					if(a[l1] < b[l2]) now[++cnt] = a[l1++];
    					else now[++cnt] = b[l2++];
    				} else if(l1 <= r1) now[++cnt] = a[l1++];
    				else now[++cnt] = b[l2++];
    			}
    //			cout << "now: ";
    //			for(int i = 1; i <= cnt; i++) cout << now[i] << " ";
    //			cout << '
    ';
    			ans[++tot] = now[cnt / 2 + 1];
    		}
    	}
    	for(int i = 1; i < tot; i++) cout << ans[i] << '
    ';
    	cout << ans[tot];
    }
    
    int main() {
    	freopen("median.in", "r", stdin);
    	freopen("median.out", "w", stdout);
    	n = read(), m = read();
    	int maxn = 0;
    	for(int i = 1; i <= n; i++) a[i] = read(), maxn = max(maxn, a[i]);
    	for(int i = 1; i <= n; i++) b[i] = read(), maxn = max(maxn, a[i]);
    	if(n <= 1000 && m <= 2000) return solve(), 0;
    	while(m--) {
    		opt = read();
    		if(opt == 1) {
    			x = read(), y = read(), z = read();
    			if(!x) a[y] = z;
    			else b[y] = z;
    			maxn = max(maxn, z);
    		} else if(opt == 2) {
    			l1 = read(), r1 = read(), l2 = read(), r2 = read();
    			int l = 0, r = maxn, len = (r1 - l1 + 1 + r2 - l2 + 1) / 2 + 1, ans; 
    			while(l <= r) {
    				int mid = (l + r) >> 1;
    				int now1 = upper_bound(a + l1, a + r1 + 1, mid) - (a + l1);
    				int now2 = upper_bound(b + l2, b + r2 + 1, mid) - (b + l2);
    				if(now1 + now2 >= len) {
    					ans = mid;
    					r = mid - 1;
    					r1 = l1 + now1 - 1;
    					r2 = l2 + now2 - 1;
    				}
    				else {
    					l = mid + 1;
    					len -= now1 + now2;
    					l1 = l1 + now1;
    					l2 = l2 + now2;
    				}
    			}
    			cout << ans << '
    ';
    		}
    	}
    	return 0;
    }
    

    正解(1)(要九九八,不要九十八,只需一点五,AC带回家)

    #include<cstdio>
    #include<algorithm>
    const int N = 5e5 + 10;
    int ri() {
    	char c = getchar(); int x = 0, f = 1; for(;c < '0' || c > '9'; c = getchar()) if(c == '-') f = -1;
    	for(;c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) - '0' + c; return x * f;
    }
    int a[N], b[N];
    int Cal(int l, int r, int *a, int st, int ed, int *b) {
    	int p = r - l + 1 + ed - st + 1 >> 1, L = l, R = r;
    	for(;L <= R;) {
    		int m = L + R >> 1, c = p - (m - l + 1) + st;
    		if(c == st - 1 && m - l == p && a[m] <= b[st]) return a[m];
    		if(c < st) {R = m - 1; continue;}
    		else if(c > ed) {L = m + 1; continue;}
    		if(a[m] >= b[c] && (a[m] <= b[c + 1] || c == ed)) return a[m];
    		if(a[m] >= b[c]) R = m - 1;
    		else L = m + 1;
    	}
    	return 0;
    }
    int main() {
    	freopen("median.in","r",stdin);
    	freopen("median.out","w",stdout);
    	int n = ri(), m = ri();
    	for(int i = 1;i <= n; ++i) a[i] = ri();
    	for(int i = 1;i <= n; ++i) b[i] = ri();
    	for(;m--;) {
    		int op = ri();
    		if(op == 1) {
    			int w = ri(), x = ri(), y = ri();
    			!w ? a[x] = y : b[x] = y;
    		} 
    		else {
    			int l = ri(), r = ri(), l1 = ri(), r1 = ri(), x;
    			if(x = Cal(l, r, a, l1, r1, b)) printf("%d
    ", x);
    			else printf("%d
    ", Cal(l1, r1, b, l, r, a));
    		}
    	}
    	return 0;
    }
    /*
    6 1
    1 2 4 5 6 7
    1 1 3 5 6 7
    2 1 6 1 1
    */
    

    正解(2)

    #include <bits/stdc++.h>
    
    int ri() {
    	char c = getchar(); int x = 0, f = 1; for(;c < '0' || c > '9'; c = getchar()) if(c == '-') f = -1;
    	for(;c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) - '0' + c; return x * f;
    }
    const int N = 5e5+50;
    
    int a[N], b[N];
    
    int kth(int ta[], int sa, int tb[], int sb, int k) {
    	if (sa > sb) return kth(tb, sb, ta, sa, k);
    	if (sa == 0) return tb[k];
    	if (k == 1) return std::min(ta[1], tb[1]);
    	int ka = std::min(sa, k/2), kb = k - ka;
    	if (ta[ka] < tb[kb]) return kth(ta+ka, sa-ka, tb, sb, k-ka);
    	return kth(ta, sa, tb+kb, sb-kb, k-kb);
    }
    
    int query(int la, int ra, int lb, int rb) {
    	int sa = ra-la+1, sb = rb-lb+1, siz = sa + sb;
    	return kth(a+la-1, sa, b+lb-1, sb, siz/2+1);
    }
    
    int main() {
    	freopen("median.in", "r", stdin);
    	freopen("median.out", "w", stdout);
    	int n, m;
    	n = ri(); m = ri();
    	for (int i = 1; i <= n; i++) a[i] = ri();
    	for (int i = 1; i <= n; i++) b[i] = ri();
    	for (int opt; m--; ) {
    		opt = ri();
    		if (opt == 2) {
    			int la = ri(), ra = ri(), lb = ri(), rb = ri();
    			printf("%d
    ", query(la, ra, lb, rb));
    		} else {
    			int p = ri(), pos = ri(), val = ri();
    			if (p == 0) a[pos] = val;
    			else b[pos] = val;
    		}
    	}
    	return 0;
    }
    /*
    5 5
    12 41 46 68 69
    35 61 82 84 96
    2 1 4 3 5
    1 0 5 75
    2 2 4 3 4
    2 3 4 1 5
    2 1 4 2 4
    */
    
    

    T2

    考场爆零代码

    /*
    By:Loceaner
    */
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #define ll long long
    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 = 2e5 + 11;
    
    int n, A, B, C, D;
    int a[N];
    ll f[N], dp[N];
    
    
    ll calc(int x) {
    	return 1LL * A * x * x * x + B * x * x + C * x + D;
    }
    
    int minn[1011][1011];
    
    inline int query(int l, int r) {
    	int k = log2(r - l + 1);
    	return min(minn[l][k], minn[r - (1 << k) + 1][k]);
    }
    
    void solve1() {
    	memset(dp, -0x3f, sizeof(dp));
    	dp[0] = 0;
    	for(int i = 1; i <= n; i++) {
    		for(int j = 1; j <= i; j++) {
    			dp[i] = max(dp[i], dp[j - 1] + calc(query(j, i)));
    		}
    	}
    	cout << dp[n] << '
    ';
    	return;
    }
    
    void solve2() {
    	memset(dp, -0x3f, sizeof(dp));
    	dp[0] = 0;
    	for(int i = 1; i <= n; i++) {
    		for(int j = 1; j <= n; j++) {
    			dp[i] = max(dp[i], dp[j - 1] + calc(minn[j][i]));
    		}
    	}
    	cout << dp[n] << '
    ';
    	return;
    }
    
    int main() {
    	freopen("min.in", "r", stdin);
    	freopen("min.out", "w", stdout);
    	n = read(), A = read(), B = read(), C = read(), D = read();
    	for(int i = 1; i <= n; i++) a[i] = read(), f[i] = calc(a[i]), minn[i][0] = a[i];
    	for(int j = 1; (1 << j) <= n; j++) 
    		for(int i = 1; i <= n; i++) 
    			minn[i][j] = min(minn[i][j - 1], minn[i + (1 << (j - 1))][j - 1]);
    //	for(int i = 1; i <= n; i++) cout << f[i] << ' ';
    	if(n <= 1000) return solve1(), 0;
    	if(A == 0 && B == 0 && C <= 0) return solve2(), 0;
    	else for(int i = 1;i <= n; ++i) if(fabs(calc(a[i])) >= 1e12) {return printf("%d
    ", a[i]), 0;};
    	return 0;
    }
    
    

    然后发现是爆了(long long),改过来就30了!

    /*
    By:Loceaner
    */
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #define ll long long
    //#define int long long
    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 = 2e5 + 11;
    
    int n, A, B, C, D;
    int a[N];
    ll f[N], dp[N];
    
    
    ll calc(int x) {
    	return 1LL * A * x * x * x + 1LL * B * x * x + 1LL * C * x + 1LL * D;
    }
    
    int minn[400011][20];
    
    inline int query(int l, int r) {
    	int k = log2(r - l + 1);
    	return min(minn[l][k], minn[r - (1 << k) + 1][k]);
    }
    
    void solve1() {
    	memset(dp, -0x3f, sizeof(dp));
    	dp[0] = 0;
    	for(int i = 1; i <= n; i++) {
    		for(int j = 1; j <= i; j++) {
    			dp[i] = max(dp[i], dp[j - 1] + calc(query(j, i)));
    		}
    	}
    	cout << dp[n] << '
    ';
    	return;
    }
    int main() {
    	freopen("min.in", "r", stdin);
    	freopen("min.out", "w", stdout);
    	n = read(), A = read(), B = read(), C = read(), D = read();
    	for(int i = 1; i <= n; i++) a[i] = read(), minn[i][0] = a[i];
    	for(int j = 1; (1 << j) <= n; j++) 
    		for(int i = 1; i <= n; i++) 
    			minn[i][j] = min(minn[i][j - 1], minn[i + (1 << (j - 1))][j - 1]);
    	solve1();
    	return 0;
    }
    
    

    正解

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    const int Nt = 524287; const long long inf = 0x3f3f3f3f3f3f3f3f;
    int ri() {
        char c = getchar(); int x = 0, f = 1; for(;c < '0' || c > '9'; c = getchar()) if(c == '-') f = -1;
        for(;c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) - '0' + c; return x * f;
    }
    int a[Nt], st[Nt], tp, n, A, B, C, D;
    long long T[Nt << 1], f[Nt], mx[Nt];
    
    void Up(int i, long long x)
    {for(T[i += Nt] = x; i >>= 1;) T[i] = std::max(T[i << 1], T[i << 1 | 1]);}
    
    long long Cal(long long x) {return ((A * x + B) * x + C) * x + D;}
    
    int main() {
    	freopen("min.in","r",stdin);
    	freopen("min.out","w",stdout);
        n = ri(); A = ri(); B = ri(); C = ri(); D = ri();
        for(int i = 1;i <= n; ++i) a[i] = ri();
        std::memset(T, -0x3f, sizeof(T));
        f[0] = 0; mx[1] = 0; st[tp = 1] = a[1]; Up(1, Cal(a[1]));
        for(int i = 1;i <= n; ++i) {
            f[i] = T[1]; long long x = f[i];
            for(;st[tp] > a[i + 1] && tp;) x = std::max(x, mx[tp]), Up(tp--, -inf);
            st[++tp] = a[i + 1]; mx[tp] = x; Up(tp, x + Cal(st[tp]));
        }
        printf("%lld
    ", f[n]);
        return 0;
    }
    

    T3

    神仙正解

    #include<cstdio>
    #include<algorithm>
    #define ls p << 1
    #define rs p << 1 | 1
    #define rt 1, 1, Q
    const int N = 1e5 + 10, Y = 2e5 + 10, P = 1e9 + 7;
    int ri() {
    	char c = getchar(); int x = 0, f = 1; for(;c < '0' || c > '9'; c = getchar()) if(c == '-') f = -1;
    	for(;c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) - '0' + c; return x * f;
    }
    int t[N << 2], tm[N << 2], c[Y], b[Y], l[Y], r[Y], pr[Y], to[Y << 1], nx[Y << 1], Q, n, m, k, H;
    void add(int x, int p) {to[++H] = 1LL * to[pr[x]] * (1 - p) % P; nx[H] = pr[x]; pr[x] = H;}
    struct D {int l, r;} q[N];
    struct X {int x, y, p;}p[Y];
    bool cmp1(X a, X b) {return a.y < b.y;}
    bool cmp2(D a, D b) {return a.l == b.l ? a.r < b.r : a.l < b.l;}
    int Pow(int x, int k) {
    	int r = 1;
    	for(;k;x = 1LL * x * x % P, k >>= 1) if(k & 1) r = 1LL * r * x % P;
    	return r;
    }
    void B(int p, int L, int R) {
    	tm[p] = 1; if(L == R) return void(t[p] = 1);
    	int m = L + R >> 1; B(ls, L, m); B(rs, m + 1, R); 
    	t[p] = t[ls] + t[rs];
    }
    void Tag(int p, int v) {tm[p] = 1LL * tm[p] * v % P; t[p] = 1LL * t[p] * v % P;}
    void Pd(int p) {if(tm[p] != 1) Tag(ls, tm[p]), Tag(rs, tm[p]), tm[p] = 1;}
    void M(int p, int L, int R, int st, int ed, int v) {
    	if(L == st && ed == R) return Tag(p, v);
    	int m = L + R >> 1; Pd(p);
    	if(st <= m) M(ls, L, m, st, std::min(ed, m), v);
    	if(ed > m) M(rs, m + 1, R, std::max(st, m + 1), ed, v);
    	t[p] = (t[ls] + t[rs]) % P;
    }
    void C(int x) {
    	if(l[x] > r[x]) return ; 
    	int m = Pow(1 - (to[pr[x]] - b[x]) % P, P - 2); pr[x] = nx[pr[x]]; 
    	M(rt, l[x], r[x], 1LL * (1 - (to[pr[x]] - b[x]) % P) * m % P);
    }
    int main() {
    	freopen("max.in","r",stdin);
    	freopen("max.out","w",stdout);
    	n = ri(); m = ri(); Q = ri(); int tp = 0;
    	for(int i = 1;i <= m; ++i) {
    		int x = ri(), y = ri(), px = ri();
    		if(!px || !y) continue;
    		p[++tp].x = x; p[tp].y = y; p[tp].p = px;
    	}
    	std::sort(p + 1, p + tp + 1, cmp1);
    	for(int i = 1;i <= n; ++i) to[++H] = 1, pr[i] = H;
    	for(int i = 1;i <= tp; ++i) add(p[i].x, p[i].p);
    	for(int i = 1;i <= n; ++i) b[i] = to[pr[i]];
    	for(int i = 1;i <= Q; ++i) q[i].l = ri(), q[i].r = ri();
    	std::sort(q + 1, q + Q + 1, cmp2);
    	int L = 1, R = 0; 
        for(int i = 1;i <= n; ++i) {
            for(;L <= R && q[L].r < i; ++L) ;
            for(;q[R + 1].l <= i && R < Q; ++R) ;
            l[i] = L; r[i] = R;
        } 
        B(rt); int A = 0; p[0].y = 0;
        for(int i = tp, j; i; i = j) {
        	for(j = i;p[j].y == p[i].y && j; --j) C(p[j].x);
        	A = (A + 1LL * t[1] * (p[i].y - p[j].y)) % P;
        }
        A = (1LL * p[tp].y * Q - A) % P;
        printf("%d
    ", (A + P) % P);
    	return 0;
    }
    
  • 相关阅读:
    html中label及加上属性for之后的用法
    Django中利用filter与simple_tag为前端自定义函数的实现方法
    关于自动编译iOS工程,生成app及ipa文件的方法-备
    ios打包ipa的四种实用方法(.app转.ipa)-备
    为GCD队列绑定NSObject类型上下文数据-利用__bridge_retained(transfer)转移内存管理权-备
    GCD使用经验与技巧浅谈--备
    h5与iOS的wkwebview不兼容问题
    cocoaPods 安装和应用
    .a静态库的注意事项
    UIApplication详解再解-备
  • 原文地址:https://www.cnblogs.com/loceaner/p/11679310.html
Copyright © 2020-2023  润新知