zoukankan      html  css  js  c++  java
  • 题解:AtCoder Beginner Contest 189

    C - Mandarin Orange

    提供一种不一样的 (mathcal{O}(n log n)) 的方法。

    设对于第 (i) 个位置,左边第一个大于它的位置记为 (L_i) ,右边第一个大于它的位置记为 (R_i)

    发现对于第 (i) 个位置的值作为 (x) 时的最优解即为 ((R_i-L_i-1) imes val_i)

    可以使用双向链表处理,具体操作见代码。

    int n, arr[N], id[N], Nxt[N], Pre[N];
    inline bool cmp(int A, int B) {return arr[A] == arr[B] ? A < B : arr[A] > arr[B];}
    int main() {
    	scanf("%d", &n);
    	forn(i,1,n) scanf("%d", arr+i), Pre[i] = i-1, Nxt[i] = i+1, id[i] = i;
    	int Ans = 0;
    	sort(id+1, id+n+1, cmp);
    	forn(i,1,n) {
    		int l = Pre[id[i]], r = Nxt[id[i]];
    		Nxt[l] = r,Pre[r] = l;
    		Ans = Max(Ans, (r-l-1) * arr[id[i]]);
    	}
    	printf("%d
    ", Ans);
    	return 0;
    }
    

    D - Logical Expression

    简单递推题。

    (T_i)(F_i) 分别表示前 (i) 个运算符计算结果的为 ( ext{True})( ext{False}) 的数量。

    如果第 (i) 个计算符为 AND ,则有

    [T_i = T_{i-1} ]

    [F_i = F_{i-1} imes 2 + T_{i-1} ]

    否则

    [F_i = F_{i-1} ]

    [T_i = T_{i-1} imes 2 + F_{i-1} ]

    答案即为 (T_n)

    E - Rotate and Flip

    这道题可以不用矩阵,也并不麻烦。

    观察每个操作:

    opt1 ((x,y) ightarrow (y,-x))

    opt2 ((x,y) ightarrow (-y,x))

    opt3 ((x,y) ightarrow (2 imes p-x,y))

    opt4 ((x,y) ightarrow (x,2 imes p-y))

    可以发现对于任何几种操作相加,对于原来的横纵坐标,都能表示成

    ((sum_x ext{opt}_x x, sum_y ext{opt}_y y))(( sum_y ext{opt}_y y,sum_x ext{opt}_x x))

    (sum) 表示一个值, ( ext{opt}) 表示正负号, (x/y) 表示原来横坐标或纵坐标的值

    在具体操作时,只需要离线处理,维护 (sum_{x/y}) , ( ext{opt}_{x/y}) , 是否翻转横纵坐标, 5 个变量即可。

    inline bool cmp(int NA, int NB) {return A[NA] < A[NB];}
    int main() {
    	scanf("%d", &n);
    	forn(i,1,n) scanf("%d%d", X+i, Y+i);
    	scanf("%d", &m);
    	forn(i,1,m) {
    		scanf("%d", opt+i);
    		if(opt[i] > 2) scanf("%d", p+i);
    	}
    	scanf("%d", &q);
    	forn(i,1,q) scanf("%d%d", A+i, B+i), id[i] = i;
    	sort(id+1, id+q+1, cmp);
    	LL trn = 0, Xopt = 1, Yopt = 1, Xsum = 0, Ysum = 0;
    	int j = 1;
    	forn(i,1,m+1) {
    		while(A[id[j]] == i-1) {
    			Xans[id[j]] = Xsum + Xopt*1ll*X[B[id[j]]];
    			Yans[id[j]] = Ysum + Yopt*1ll*Y[B[id[j]]];
    			if(trn) swap(Xans[id[j]], Yans[id[j]]);
    			++j;
    		}
    		if(opt[i] == 1) {
    			if(trn) {
    				Yopt = -Yopt;
    				Ysum = -Ysum;
    			} else {
    				Xopt = -Xopt;
    				Xsum = -Xsum;	
    			}
    			trn^=1;
    		} else if(opt[i] == 2) {
    			if(trn) {
    				Xopt = -Xopt;
    				Xsum = -Xsum;	
    			} else {
    				Yopt = -Yopt;
    				Ysum = -Ysum;
    			}
    			trn^=1;
    		} else if(opt[i] == 3) {
    			if(trn) {
    				Ysum = 2ll*p[i] - Ysum;
    				Yopt = -Yopt;
    			} else {
    				Xsum = 2ll*p[i] - Xsum;
    				Xopt = -Xopt;	
    			}
    		} else {
    			if(trn) {
    				Xsum = 2ll*p[i] - Xsum;
    				Xopt = -Xopt;
    			} else {
    				Ysum = 2ll*p[i] - Ysum;
    				Yopt = -Yopt;
    			}
    		}
    	}
    	forn(i,1,q) printf("%lld %lld
    ", Xans[i], Yans[i]);
    	return 0;
    }
    

    F - Sugoroku2

    (f_i) 表示从第 (i) 个格子到终点的次数期望,显然有:

    ( egin{cases} f_i = displaystyle{0} & igeq n\ f_i = displaystyle{f_0} & iin A \ f_i = displaystyle{frac{1}{m}sum_{j=i+1}^{i+m} f_j}+1 & ext{otherwise}\ end{cases} )

    这个式子不能直接求,但是每一个 (f_i) 可以表示成关于 (f_0) 的一次函数形式,最终为获得一个形如 (f_0 = k imes f_0+b) 的式子,直接解方程即可。

    所以可以用后缀和优化的 DP 来求出每一个一次函数,总复杂度仅为 (mathcal{O}(n))

    另附本题加强版

    #include<bits/stdc++.h>
    #define forn(i,s,t) for(register int i=(s);i<=(t);++i)
    #define form(i,s,t) for(register int i=(s);i>=(t);--i)
    using namespace std;
    const int N = 2e5+3;
    int n, m, k, a[N]; bool bck[N];
    long double f1[N], f2[N], suf1[N], suf2[N];
    int main() {
    	scanf("%d%d%d", &n, &m, &k);
    	long double C = (long double)1.0/m;
    	forn(i,1,k) scanf("%d", a+i), bck[a[i]] = 1;
    	form(i,n-1,0) {
    		if(bck[i]) {
    			suf1[i] = suf1[i+1];
    			suf2[i] = suf2[i+1] + 1.0;
    			continue ;
    		}
    		f1[i] = C*(suf1[i+1] - suf1[i+m+1]) + 1;
    		f2[i] = C*(suf2[i+1] - suf2[i+m+1]);
    		suf1[i] = suf1[i+1] + f1[i];
    		suf2[i] = suf2[i+1] + f2[i];
    	}
    	if(1-f2[0] < 1e-6) puts("-1");
    	else printf("%.4Lf
    ", f1[0]/(1-f2[0]));
    	return 0;
    }
    
  • 相关阅读:
    1063. Set Similarity
    A1047. Student List for Course
    A1039. Course List for Student
    最大公约数、素数、分数运算、超长整数计算总结
    A1024. Palindromic Number
    A1023. Have Fun with Numbers
    A1059. Prime Factors
    A1096. Consecutive Factors
    A1078. Hashing
    A1015. Reversible Primes
  • 原文地址:https://www.cnblogs.com/Ax-Dea/p/14320381.html
Copyright © 2011-2022 走看看