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]));
    }
    
  • 相关阅读:
    HDU 6182 A Math Problem 水题
    HDU 6186 CS Course 位运算 思维
    HDU 6188 Duizi and Shunzi 贪心 思维
    HDU 2824 The Euler function 欧拉函数
    HDU 3037 Saving Beans 多重集合的结合 lucas定理
    HDU 3923 Invoker Polya定理
    FZU 2282 Wand 组合数学 错排公式
    HDU 1452 Happy 2004 数论
    HDU 5778 abs 数论
    欧拉回路【判断连通+度数为偶】
  • 原文地址:https://www.cnblogs.com/sduwh/p/14319164.html
Copyright © 2011-2022 走看看