zoukankan      html  css  js  c++  java
  • ABC189

    B. Alcoholic

    我以为不会卡精度没有乘100,wa3次

    C. Mandarin Orange

    正解应该是单调栈,经典题目 最大矩形

    但是 (n) 范围是 1e4

    直接 (O(nlogn + n^2)) 用st表过了,跑了960ms / 1500ms

    /*
     * @Author: zhl
     * @LastEditTime: 2021-01-23 20:19:20
     */
    #include<bits/stdc++.h>
    using namespace std;
    
    const int N = 2e5 + 10;
    typedef long long ll;
    int f[N][32];
    int A[N];
    
    int n, m, x, y;
    void init() {
    	for (int i = 1; i <= n; i++) {
    		f[i][0] = A[i];
    	}
    	for (int j = 1; (1 << j) <= n; j++) {
    		for (int i = 1; i + (1 << j) - 1 <= n; i++) {
    			f[i][j] = min(f[i][j - 1], f[i + (1 << (j-1))][j - 1]);
    		}
    	}
    }
    
    int query(int l, int r) {
    	int k = log2(r - l + 1);
    	return min(f[l][k], f[r - (1 << k) + 1][k]);
    }
    int main(){
        scanf("%d",&n);
        for (int i = 1;i <= n;i++)scanf("%d", A + i);
        init();
        
        ll ans = 0;
        
        for(int i = 1;i <= n;i++){
            for(int j = 1;j <= i;j++){
                ans = max(ans, 1ll * query(j, i) * (i - j + 1));
            }
        }
        printf("%lld
    ", ans);
    }
    
    

    D. Logical Expression

    感觉肯定是个二进制,最低位填一个 1, 地位到高位从上往下

    n = int(input())
    ans, now = 1, 1
    
    for _ in range(n):
        s = input()
        now = now * 2
        if s == "OR":
            ans += now
    print(ans)
    

    E. Rotate and Flip

    题意

    平面上有 (n) 个点,每次对所有的点操做,操作 (m)

    有如下 4 种操作

    1 : 所有点顺时针绕原点旋转 90°

    2 : 所有点逆时针绕原点旋转 90°

    3 p : 所有点关于 (x = p) 对称翻转

    4 p : 所有点关于 (y = p) 对称翻转

    (q) 次询问,每次询问第 (a_i) 个点在 (b_i) 次操作后的坐标

    $ 1 le n,m,q le 2e5 $

    (-10^9 le x_i,y_i,p_i le 10^9)

    思路

    设点坐标为 ((x,y))

    1.顺时针: ((y,-x))

    2.逆时针: ((-y,x))

    3 : ((2p-x,y))

    4 : ((x,2p-y))

    发现只需要维护两边的符号和常数项,以及 (x,y) 是否交换了位置

    int fx, fy, ax, ay, rev; // fx,fy 是符号, ax,ay 是常数项, rev表示 x,y 是否对换
    void cal(int xx, int yy, int& resx, int& resy) {
    	if (rev)swap(xx, yy);
    	resx = xx * fx + ax;
    	resy = yy * fy + ay;
    }
    if (op[i] == 1) {
    	//(y,-x)
    	swap(fx, fy); swap(ax, ay); rev ^= 1, fy *= -1, ay *= -1;
    }
    else if (op[i] == 2) {
    	//(-y,x)
    	swap(fx, fy); swap(ax, ay); rev ^= 1, fx *= -1, ax *= -1;
    }
    else if (op[i] == 3) {
    	//(2p - x,y)
    	ax *= -1, fx *= -1;
    	ax += 2 * p[i];
    }
    else {
    	//(x, 2p - y)
    	ay *= -1, fy *= -1;
    	ay += 2 * p[i];
    }
    

    离线查询就可以,感觉有点麻烦,不知道别人怎么写的

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    
    const int N = 2e5 + 10;
    typedef long long ll;
    
    int fx, fy, ax, ay, rev;
    int n, m, q;
    int x[N], y[N];
    int ansx[N], ansy[N];
    int op[N], p[N];
    
    struct query {
    	int op, idx, id;
    	bool operator < (const query& b)const {
    		return op < b.op;
    	}
    }Q[N];
    
    void cal(int xx, int yy, int& resx, int& resy) {
    	if (rev)swap(xx, yy);
    	resx = xx * fx + ax;
    	resy = yy * fy + ay;
    }
    signed main() {
    	scanf("%lld", &n);
    	for (int i = 1; i <= n; i++) {
    		scanf("%lld%lld", x + i, y + i);
    	}
    	scanf("%lld", &m);
    	for (int i = 1; i <= m; i++) {
    		scanf("%lld", op + i);
    		if (op[i] > 2)scanf("%lld", p + i);
    	}
    	scanf("%lld", &q);
    
    	for (int i = 1; i <= q; i++) {
    		scanf("%lld%lld", &Q[i].op, &Q[i].idx);
    		Q[i].id = i;
    	}
    	sort(Q + 1, Q + 1 + q);
    
    	int idx = 1;
    
    	fx = fy = 1; ax = ay = 0; rev = 0;
    
    	while (idx <= q and Q[idx].op == 0) {
    		int pos = Q[idx].idx; int id = Q[idx].id;
    		if (rev == 1)cal(y[pos], x[pos], ansx[id], ansy[id]);
    		else cal(x[pos], y[pos], ansx[id], ansy[id]);
    		idx++;
    	}
    
    	for (int i = 1; i <= m; i++) {
    		if (op[i] == 1) {
    			//(
    			swap(fx, fy); swap(ax, ay); rev ^= 1, fy *= -1, ay *= -1;
    		}
    		else if (op[i] == 2) {
    			swap(fx, fy); swap(ax, ay); rev ^= 1, fx *= -1, ax *= -1;
    		}
    		else if (op[i] == 3) {
    			ax *= -1, fx *= -1;
    			ax += 2 * p[i];
    		}
    		else {
    			ay *= -1, fy *= -1;
    			ay += 2 * p[i];
    		}
    		while (idx <= q and Q[idx].op == i) {
    			int pos = Q[idx].idx; int id = Q[idx].id;
    			cal(x[pos], y[pos], ansx[id], ansy[id]);
    			idx++;
    		}
    	}
    	for (int i = 1; i <= q; i++) {
    		printf("%lld %lld
    ", ansx[i], ansy[i]);
    	}
    }
    

    F. Sugoroku2

    题意

    从 0 出发,每次投一次 (m) 个面的骰子(1-m) ,投出多少前进多少格,到达 n 或者经过 n 就算胜利。

    有 k 个点,只要恰好到达这些点,就会被传送回起点,问胜利所需投骰子的期望次数,若无法取胜,则输出 -1

    思路

    设 f[i] 表示从 i 位置出发,胜利的期望步数

    有 $f[i] = dfrac {sum_{j = 1}^ m f[i + j]} m + 1 $

    于是可以从后往前推,若与原点连通,则 (f[i] = f[0]) , 可以设 (f[i] = a_icdot f[0] + b_i)

    (f[i] = dfrac {sacdot f[0] + sb} m + 1) , sa, sb 表示 (sum_{j=i+1}^{i + m})(a_i)(b_i) 的和

    维护一个定长的和 sa,sb 就可以

    #include<bits/stdc++.h>
    using namespace std;
    
    const int N = 2e5 + 10;
    typedef long long ll;
    
    int n, m, k;
    int vis[N];
    double a[N], b[N], sa, sb;
    int main(){
        scanf("%d%d%d", &n, &m, &k);
        for(int i = 1;i <= k;i++){
            int x;scanf("%d", &x);vis[x] = 1;
        }
        for(int i = n - 1;i >= 0;i--){
            if (vis[i])a[i] = 1, b[i] = 0;
            else{
                a[i] = sa / m;b[i] = sb / m + 1;
            }
            sa += a[i] - a[i + m];
            sb += b[i] - b[i + m];
        }
        if (fabs(a[0] - 1.0) < 1e-8)puts("-1");
        else printf("%.8f
    ", b[0] / (1 - a[0]));
    }
    
  • 相关阅读:
    java中的静态变量与实例变量
    Java中的关键字this
    继承和多类的基础(C++)
    11-1:(42)接雨水
    10-2
    10-1
    9-2
    9-1
    8-2
    8-1
  • 原文地址:https://www.cnblogs.com/sduwh/p/14319164.html
Copyright © 2011-2022 走看看