ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Cycle Function - 题解【二分】

2022-04-21 02:01:54  阅读:262  来源: 互联网

标签:Function __ 题解 a1 abs ans xs line Cycle


题面

这是2019四川省赛的C题。这里放上CodeForces的链接:C. Cycle Function - Codeforces

Fish is learning functions! He has a linear function \(f(x)=Ax+B\) and \(N\) numbers \(x_1,x_2,⋯,x_N\). Now he is curious about for each function \(g(x)\) in

\[ \left\{ \begin{matrix} g_1(x)=c_1x+d_1\\ g_2(x)=c_2x+d_2\\ \vdots\\ g_M(x)=c_Mx+d_M \end{matrix} \right\} \]

how to calculate the difference between \(f(g(x))\) and \(g(f(x))\).

As smart as Fish is, he soon comes up with a function \(D(x)=|f(g(x))−x|+|g(f(x))−x|\) and uses the sum over \(x_1,x_2,⋯,x_N\) as the difference.

Can you tell him all the differences immediately?

Input
The first line of input contains an integer \(T\), representing the number of test cases.

Then for each test case:

The first line contains two integers \(N, M\) as mentioned above and then two real numbers \(A, B\) indicating the given function \(f(x)=Ax+B\).

The second line contains \(N\) real numbers \(x_1,x_2,⋯,x_N\).

Then \(M\) lines follow, each line containing two real numbers \(c_i, d_i\) indicating a function \(g_i(x)=c_ix+d_i\) mentioned above.

All numbers in the same line are separated by one space.

Output
For each test case, you should output Case x: in the first line, where \(x\) indicates the case number starting from \(1\).

Then \(M\) lines follow, the \(i\)-th line of which contains a real number representing the difference for given function \(g_i(x)\).

Your answers will be considered correct if its absolute error does not exceed \(10^{−6}\).

Limits

time limit per test: 5 seconds
memory limit per test: 256 megabytes
input: standard input
output: standard output

Note

\(1≤T≤100\)
\(1≤N,M≤10^5\)
\(−100≤A,B,x_i,c_i,d_i≤100\)
For \(90\%\) test cases: \(max(N,M)≤1000\)

Example Input

2
3 2 2.0 3.0
1.0 2.0 3.0
0.4 -2.0
0.6 -5.0
3 2 2.5 2.0
1.0 2.0 3.0
0.4 -2.0
0.6 -5.0

Example Output

Case 1:
7.800000
28.200000
Case 2:
12.600000
36.900000

大意

给定一个线性函数\(f(x)=Ax+B\)和一个线性函数组\(g_i(x)=c_ix+d_i\),定义函数\(D(x)=|f(g(x))−x|+|g(f(x))−x|\),对于给定的一组数\(x_i,\enspace i=i,2,\dots,n\),求关于线性函数组里的每个函数,$ \sum_{i=1}^{n} D(x_i)$的值。

题解

我们对这两个绝对值符号里面的内容做一下数学变换,记\(Ac-1=a,Ad+B=p,Bc+d=q\):

\[f(g(x))-x=A(cx+d)+B=Acx+Ad+B-x=(Ac-1)x+(Ad+B)=ax+p \]

\[g(f(x))-x=c(Ax+B)+d=Acx+Bc+d-x=(Ac-1)x+(Bc+d)=ax+q \]

式子变得简单了不少。但是绝对值仍然是一个让人非常讨厌的东西,需要对正数与负数进行分类讨论。而且,本题有至多1e5个变量和 1e5个函数,虽然时间限制是5秒,但是平方复杂度的暴力解法必定会超时。我们考虑到,对于线性函数\(F(x)=kx+b\),当\(k=0\)时值永远为\(b\),否则其零点为\(x_0=-\frac{b}{k}\),因此我们只需要特判系数\(a\)是否为0,然后考虑大于\(x_0\)的数以及不大于\(x_0\)的数,分别计算即可,一连串数据的求和可以使用前缀和来维护,分界点排序后使用二分查找函数lower_bound即可。这题知道思路了就很简单,但是确实蛮难想的……

排序复杂度为\(O(NlogN)\),对每个函数二分查找总复杂度为\(O(MlogN)\),综合复杂度为\(O((M+N)logN)\),可以接受。

另:本题卡输入输出,要使用C风格的输入输出或者手搓快读快写。Java或者Python选手还是放弃吧o( ̄▽ ̄)ブ笔者使用关闭流同步的cin\cout超时,改scanf\printf只用了2000ms……

下面是代码:

#include <bits/stdc++.h>
#define GRP int T;cin>>T;rep(C,1,T)
#define FAST ios::sync_with_stdio(false);cin.tie(0);
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define rrep(i,a,b) for(int i=a;i>=b;--i)
#define elif else if
#define mem(arr,val) memset(arr,val,sizeof(arr))
typedef long long ll;
typedef unsigned long long ull;
using namespace std;

const double EPS = 1e-8;
int n, m;
double a, b;
double xs[100010], x[100010], c, d;
double ans;

int main() {
	xs[0] = 0;
	GRP {
		scanf("%d %d %lf %lf", &n, &m, &a, &b);
		printf("Case %d:\n", C);
		//读入并排序,求前缀和
		rep(i, 1, n) {
			scanf("%lf", x + i);
		}
		sort(x + 1, x + 1 + n);
		rep(i, 1, n) {
			xs[i] = xs[i - 1] + x[i];
		}
		//处理每个g(x)
		rep(i, 1, m) {
			scanf("%lf %lf", &c, &d);
			ans = 0;
			double a1 = a * c - 1, p = a * d + b, q = b * c + d;	//计算系数
			if (abs(a1) < EPS) {					//浮点数为0应判断其绝对值小于一个极小值
				ans = (abs(p) + abs(q)) * n;
			} else {
				//寻找分界点
				int i1 = lower_bound(x + 1, x + 1 + n, -p / a1) - x - 1;
				int i2 = lower_bound(x + 1, x + 1 + n, -q / a1) - x - 1;
				//分别求值并且累加
				ans += abs(a1 * (xs[i1] - xs[0]) + p * (i1));
				ans += abs(a1 * (xs[n] - xs[i1]) + p * (n - i1));
				ans += abs(a1 * (xs[i2] - xs[0]) + q * (i2));
				ans += abs(a1 * (xs[n] - xs[i2]) + q * (n - i2));
			}
			printf("%.7lf\n", ans);
		}
	}
	return 0;
}

/*
          _           _    _            _
    /\   | |         | |  | |          (_)
   /  \  | | _____  _| |__| | ___  _ __ _ _ __   __ _
  / /\ \ | |/ _ \ \/ /  __  |/ _ \| '__| | '_ \ / _` |
 / ____ \| |  __/>  <| |  | | (_) | |  | | | | | (_| |
/_/    \_\_|\___/_/\_\_|  |_|\___/|_|  |_|_| |_|\__, |
                                                 __/ |
                                                |___/
*/

标签:Function,__,题解,a1,abs,ans,xs,line,Cycle
来源: https://www.cnblogs.com/AlexHoring/p/16172520.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有