zoukankan      html  css  js  c++  java
  • CF gym 102483(NWERC 2018) A题 解答

    分析

    题目大意:给出 (n) 个点的坐标 ((x_i, y_i)) ,其中 (iin [1,n]) ,要求构造相应的点 ((p_i,q_i))(p,q) 满足 (p_{i-1}leq p_{i},~q_{i-1}leq q_{i}),使得 (sum ((x_i-p_i)^2+(y_i-q_i)^2)) 最小。

    注意到 (x,y)(p,q) 都是分别独立的,因此只需求 (sum (x_i-p_i)^2) 最小值即可。

    先给出具体做法:对于每个 (x_k) ,都创建一个有值和 (sum) (简记为 (s)),(cnt) (简记为 (c))两个属性的结点,当当前结点 (cur)先前结点满足: (s_{cur}/c_{cur} < s_{last}/c_{last}) 时,就将 (cur)(last) 进行合并得到更新后的 (cur) ,如此下去直到最后的 (cur)(last) 满足: (s_{cur}/c_{cur} geq s_{last}/c_{last})

    其中合并方法为: 将 (s_{cur}) 加上 (s_{last})(c_{cur}) 加上 (c_{last}) ,删去 (last)

    下面说明这样做即可得到最优解:

    简便起见,分别将 (cur,last) 结点记为 (e_{i+1},e_i)(forall i)(e_i) 有属性 (s_i,c_i)(s_i/c_i) 记为 (v_i)

    (e_i) 对应的区间为 ([L,k])(e_{i+1}) 对应的区间为 ([k+1,R])

    先给出引理:对于 (frac{sum_{i=1}^n (a_i-x)^2}{n}) ,当且仅当 (x=overline a) 时取到最小值。

    证明:展开,可知 (frac{sum_{i=1}^n (a_i-x)^2}{n}) 是关于 (x) 的二次函数,由展开式可知,其在且只在 (x=overline a) 取到最小值。

    • (v_{i+1} geq v_i) 时,只需证明不合并合并的花费小即可。

    (v=(s_i+s_{i+1})/(c_i+c_{i+1}))

    由所给的做法,对于相应的 (p值) 可知在 ([L,k])(p=v_i) ,而在 ([k+1,R])(p=v_{i+1}) ,这样的 (p) 值是合法的。

    只需证明 (sum_{j=L}^R (x_j-v)^2 geq sum_{u=L}^k(x_u-v_i)^2+sum_{w=k+1}^R (x_w-v_{i+1})^2)

    由引理,

    (sum_{u=L}^k(x_u-v)^2geq sum_{u=L}^k(x_u-v_i)^2)

    (sum_{w=k+1}^R (x_w-v)^2 geq sum_{w=k+1}^R (x_w-v_{i+1})^2)

    将上两式相加即证。

    • (v_{i+1} < v_i) 时,只需证明合并不合并的花费小即可。

    由所给的做法,对于相应的 (p值) ,记在 ([L,k])(p=p_f) ,而在 ([k+1,R])(p=p_s) ,应有 (p_sgeq p_f)

    只需证明 (sum_{j=L}^R (x_j-v)^2 leq sum_{u=L}^k(x_u-p_f)^2+sum_{w=k+1}^R (x_w-p_s)^2)

    因为 (sum_{w=k+1}^R (x_w-p_s)^2 geq sum_{u=L}^k(x_u-p_f)^2)

    (sum_{u=L}^k(x_u-p_f)^2+sum_{w=k+1}^R (x_w-p_s)^2 geq sum_{u=L}^k(x_u-p_f)^2+sum_{w=k+1}^R (x_w-p_f)^2 = sum_{j=L}^R (x_j-p_f)^2)

    由引理,显然有 (sum_{j=L}^R (x_j-p_f)^2 geq sum_{j=L}^R (x_j-v)^2)

    至此证毕。

    所以对于所给的做法,每一次操作都是最优的做法,因此整个做法是最优的。

    代码:

    #pragma GCC optimize("O3")
    #include<bits/stdc++.h>
    using namespace std;
    #define endl '
    '
    #define debug(x) cerr << #x << ": " << x << endl
    #define pb(a) push_back(a)
    #define set0(a) memset(a,0,sizeof(a))
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define dwn(i,a,b) for(int i=(a);i>=(b);i--)
    #define ceil(a,b) (a+(b-1))/b
    #define INF 0x3f3f3f3f
    #define ll_INF 0x7f7f7f7f7f7f7f7f
    typedef long long ll;
    typedef pair<int,int> PII;
    typedef pair<double,double> PDD;
    
    inline int read()
    {
    	int x=0,y=1;char c=getchar();
    	while (c<'0'||c>'9') {if (c=='-') y=-1;c=getchar();}
    	while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    	return x*y;
    }
    
    const int N=1e5+5;
    const double eps=1e-12;
    int n;
    double x[N], y[N];
    
    double stk_sum[N];
    int stk_cnt[N];
    int top;
    
    double cal(double a[]){
    	set0(stk_sum), set0(stk_cnt);
    	top=0;
    	
    	rep(i, 1, n){
    		double cur_sum=a[i]; int cur_cnt=1;
    		while(top && cur_sum*stk_cnt[top]+eps<stk_sum[top]*cur_cnt){
    			cur_sum+=stk_sum[top];
    			cur_cnt+=stk_cnt[top--];
    		}
    		stk_sum[++top]=cur_sum, stk_cnt[top]=cur_cnt;
    	}		
    	
    	int id=0;
    	double res=0;
    	rep(i, 1, top) rep(j, 1, stk_cnt[i]){
    		id++;
    		double avg=stk_sum[i]/stk_cnt[i];
    		res+=(avg-a[id])*(avg-a[id]);
    	}
    	return res;
    }
    
    int main(){
    	cin>>n;
    	rep(i, 1, n) cin>>x[i]>>y[i];
    	
    	double res=cal(x)+cal(y);
    	printf("%.10lf
    ", res);	
    	
        return 0;
    }
    
  • 相关阅读:
    验证guid()类型值的函数
    jquery时期到计时插件
    最简单快速的Apache二级域名实现方法
    线程和线程的常用方法
    Mobile WEB前端研发流程
    HTML5标莶使用初级技巧
    前端开发中常见的HTML5标签乱用案例
    iPad应用的10大用户体验设计准则
    移动平台3G手机网站前端开发布局技巧汇总
    分享HTML 5的参考手册,演讲稿,电子书和教程
  • 原文地址:https://www.cnblogs.com/Tenshi/p/14757172.html
Copyright © 2011-2022 走看看