Simfonija 题解
Simfonija 题解
题意
给定两个长度为
思路
首先我们可以考虑
我们发现,答案就是这些黑线覆盖的面积。(想象一下从每一条黑线两侧延伸下来两条边,形成若干个矩形)
现在我们来考虑
假如红线现在向上平移,设绿色面积为
但是我们还有
代码:
#include<bits/stdc++.h> using namespace std; const int N = 1e5+100; const int M = 2e6+100, del = 2000000; inline int read(){ int x = 0, f = 1; char ch = getchar(); while(ch<'0' || ch>'9') {if(ch == '-') f = -1; ch = getchar();} while(ch>='0'&&ch<='9') {x = x*10+ch-48, ch = getchar();} return x * f; } int n, K; int a[N], b[N], d[N]; int e[N]; int ed[N]; int id[M<<1], idx; int main(){ // freopen("simfonija.in", "r", stdin); // freopen("simfonija.out", "w", stdout); n = read(), K = read(); for(int i = 1; i<=n; ++i){ a[i] = read(); } for(int i = 1; i<=n; ++i){ b[i] = read(); } for(int i = 1; i<=n; ++i){ d[i] = b[i] - a[i]; } sort(d+1, d+n+1); for(int i = 1; i<=n; ++i){ if(i == n || d[i+1]!=d[i]){ id[d[i]+del] = ++idx; ed[idx] = i; }//预处理每段黑边的右端点。 } int len = (n+1-K)/2; int X = d[len]; long long ans = 0; for(int i = 1; i<=(n-K); ++i){ ans+=abs(d[i]-X); }//左侧不选的答案 int lst = X; long long ret = ans; for(int i = 1; i<=K; ++i){ int nX = d[i+len]; ans+= abs(d[n-K+i]-lst);//加上右侧弃选后增加的答案 ans-= abs(d[i]-lst);//减去左侧选后减少的答案 if(nX != lst){//如果中位数有变化,则 0 值线升高,要处理面积变化。 ans-=(1ll*((n-K+i)-ed[id[lst+del]]) * (nX-lst)); ans+=(1ll*(nX-lst)*(ed[id[lst+del]] - i)); lst = nX; } ret = min(ret, ans);//答案取最小的 } printf("%lld\n", ret); return 0; }