• xsy子矩形


    • 考虑一种解题方法,枚举上下边界L,R, 然后二分答案T,我们要判断的是否存在

    [frac{(sum_j - sum_i)}{2 * (R - L + 1 + j - i)} ge T ]

    • 也就是

    [(sum_j - 2Tj) - (sumi - 2Ti) ge 2T(R - L + 1) ]

    • 维护前缀最小值即可
    • 然后这样是三次方的, 我们考虑random_shuffle一下枚举的序列, 然后查询的时候就先看一下当前的ans + eps是否可行, 不可行的话就不进行二分直接退出
    • 这样期望是会进行lnn次的二分, 就赢了
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #include<iostream>
    #define M 515
    #define ll long long
    #define mmp make_pair
    using namespace std;
    int read() {
    	int nm = 0, f = 1;
    	char c = getchar();
    	for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0';
    	return nm * f;
    }
    const double eps = 1e-10, inf = 5e13;
    double ans = -1e9;
    ll sum[M][M], n, tp, ver[M], xl, xr, yl, yr;
    pair<int, int> note[M * M];
    ll get(int xa, int ya, int xb, int yb) {
    	return sum[xb][yb] - sum[xa - 1][yb] - sum[xb][ya - 1] + sum[xa - 1][ya - 1];
    }
    
    bool check(double T, int len, int l, int r) {
    	double minn = 0, pl = 0;
    	double up = T * 2 * len;
    	for(int i = 1; i <= n; i++) {
    		double ver2 = ver[i] - T * 2 * i;
    		if(ver2 - minn >= up) {
    			if(T > ans) {
    				ans = T;
    				xl = l, yl = pl + 1, xr = r, yr = i;
    			}
    			return true;
    		}
    		if(ver2 < minn) minn = ver2, pl = i;
    	}
    	return false;
    }
    
    int main() {
    	//freopen("rectangle3.in", "r", stdin);
    	n = read();
    	for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + read();
    	for(int i = 1; i <= n; i++) for(int j = i; j <= n; j++) note[++tp] = mmp(i, j);
    	for(int i = 1; i <= tp; i++) {
    		int x = 1ll * rand() * rand() % i + 1;
    		swap(note[x], note[i]);
    	}
    	for(int i = 1; i <= tp; i++) {
    		int l = note[i].first, r = note[i].second;
    		for(int j = 1; j <= n; j++) ver[j] = get(l, 1, r, j);
    		if(!check(ans + eps, r - l + 1, l, r)) continue;
    		double L = ans, R = inf;
    		for(int j = 1; j <= 100; j++) {
    			double mid = (L + R) / 2.0;
    			if(!check(mid, r - l + 1, l, r)) R = mid;
    			else L = mid;
    		}
    	}
    //	cerr<< note[tp].first << " " << note[tp].second << "
    ";
    	printf("%.10lf
    ", ans);
    	cout << xl << " " << yl << "
    " << xr << " " << yr << "
    ";
    	return 0;
    }
    
  • 相关阅读:
    个人总结
    找水王
    nabcd需求分析
    四则运算最终篇-网页版四则运算
    第一次冲刺--个人工作总结02
    第一次冲刺--个人工作总结01
    组队APP功能点定点NABCD分析
    水王
    软件工程结对作业01
    个人工作总结06
  • 原文地址:https://www.cnblogs.com/luoyibujue/p/10713327.html
Copyright © 2020-2023  润新知