3.000000 4.6666673.000000 6.666667
线段树的一种巧妙的应用,同时让我想通了一个之前一直在思考的问题。
看到的题解一般都是第一种办法的
#include<cstdio>#include<cstring>#include<cstdlib>#include<iostream>#include<algorithm>using namespace std;typedef long long LL;const int low(int x) { return x&-x; }const int INF = 0x7FFFFFFF;const int mod = 1e9 + 7;const int maxn = 1e5 + 10;int T, n, p[maxn];struct point{int p, x, t, id;}t[maxn];struct STree{LL f[maxn << 2][3], c[maxn << 2];void clear(){memset(f, 0, sizeof(f));memset(c, 0, sizeof(c));}void add(int x, int l, int r, int u){c[x]++;if (l == r){for (int i = 0; i < 3; i++) f[x][i] = (i + 1) * p[u];}else{int m = l + r >> 1;if (u <= m) add(x << 1, l, m, u);else add(x << 1 | 1, m + 1, r, u);for (int i = 0; i < 3; i++){f[x][i] = f[x << 1][i] + f[x << 1 | 1][(c[x << 1] + i) % 3];}}}}solve;bool cmp1(const point&a, const point&b){return a.x < b.x;}bool cmp2(const point&a, const point&b){return a.t < b.t;}int main(){scanf("%d", &T);while (T--){scanf("%d", &n);solve.clear();for (int i = 1; i <= n; i++) scanf("%d", &t[i].p);for (int i = 1; i <= n; i++) scanf("%d", &t[i].x);sort(t + 1, t + n + 1, cmp1); t[0].x = 0;for (int i = 1; i <= n; i++) t[i].t = t[i].x - t[i - 1].x, t[i].id = i, p[i] = t[i].p;//solve.build(1, 1, n);sort(t + 1, t + n + 1, cmp2);double w = t[1].t, ans = 0;for (int i = 1, j = 1; i <= n; i = j){while (j <= n && t[j].t == t[i].t) solve.add(1, 1, n, t[j++].id);double now = 1.0*solve.f[1][0] / (j - 1);if (now > ans) ans = now, w = t[i].t;}printf("%.6lf %.6lf\n", w, ans);}return 0;}
第二种从后往前一个一个删除
#include<cstdio>#include<cstring>#include<cstdlib>#include<iostream>#include<algorithm>using namespace std;typedef long long LL;const int low(int x) { return x&-x; }const int INF = 0x7FFFFFFF;const int mod = 1e9 + 7;const int maxn = 1e5 + 10;int T, n, p[maxn];struct point{int p, x, t, id;}t[maxn];struct STree{LL f[maxn << 4][3], c[maxn << 4];void update(int x){for (int i = 0; i < 3; i++){f[x][i] = f[x << 1][i] + f[x << 1 | 1][i];}}void build(int x, int l, int r){c[x] = 0;if (l == r){for (int i = 3; i; i--){f[x][3 - i] = t[l].p*((l + i - 1) % 3 + 1);}}else{int m = l + r >> 1;build(x << 1, l, m);build(x << 1 | 1, m + 1, r);update(x);}}void make(int x){for (int i = 0; i < 2; i++){swap(f[x][i], f[x][i + 1]);}}void pushdown(int x){c[x] %= 3;c[x << 1] += c[x];c[x << 1 | 1] += c[x];while (c[x]--){make(x << 1);make(x << 1 | 1);}c[x] = 0;}void del(int x, int l, int r, int u){if (l == r){for (int i = 0; i < 3; i++) f[x][i] = 0;}else{if (c[x]) pushdown(x);int m = l + r >> 1;if (u <= m){del(x << 1, l, m, u);c[x << 1 | 1]++;make(x << 1 | 1);}else del(x << 1 | 1, m + 1, r, u);update(x);}}}solve;bool cmp1(const point&a, const point&b){return a.x < b.x;}bool cmp2(const point&a, const point&b){return a.t > b.t;}int main(){scanf("%d", &T);while (T--){scanf("%d", &n);for (int i = 1; i <= n; i++) scanf("%d", &t[i].p);for (int i = 1; i <= n; i++) scanf("%d", &t[i].x);sort(t + 1, t + n + 1, cmp1); t[0].x = 0;for (int i = 1; i <= n; i++) t[i].t = t[i].x - t[i - 1].x, t[i].id = i;solve.build(1, 1, n);sort(t + 1, t + n + 1, cmp2);double w, ans = 0;for (int i = 1, j = 1; i <= n; i = j){double now = 1.0*solve.f[1][0] / (n - i + 1);if (now > ans) ans = now, w = t[i].t;else if (now==ans) w=t[i].t;while (j <= n && t[j].t == t[i].t) solve.del(1, 1, n, t[j++].id);}printf("%.6lf %.6lf\n", w, ans);}return 0;}
温故而知新,这次从前面来#include<map>#include<cmath> #include<queue> #include<string>#include<vector>#include<cstdio> #include<cstring> #include<algorithm> using namespace std;#define ms(x,y) memset(x,y,sizeof(x)) #define rep(i,j,k) for(int i=j;i<=k;i++) #define per(i,j,k) for(int i=j;i>=k;i--) #define loop(i,j,k) for (int i=j;i!=-1;i=k[i]) #define inone(x) scanf("%d",&x) #define intwo(x,y) scanf("%d%d",&x,&y) #define inthr(x,y,z) scanf("%d%d%d",&x,&y,&z) typedef long long LL;const int low(int x) { return x&-x; }const int INF = 0x7FFFFFFF;const int mod = 1e9 + 7;const int N = 1e5 + 10;int T, n, p[N], t[N], a[N], b[N], c[N];int g[N << 2];double f[N << 2][3];void push(int x, int l, int r){g[l] += g[x]; g[r] += g[x];for (g[x] %= 3; g[x]; g[x]--){rep(i, 0, 1) swap(f[l][i], f[l][i + 1]);rep(i, 0, 1) swap(f[r][i], f[r][i + 1]);}}void insert(int x, int l, int r, int u, int v){if (l == r) { rep(i, 0, 2) f[x][i] = v + v * i;for (g[x] %= 3; g[x]; g[x]--)rep(i, 0, 1) swap(f[x][i], f[x][i + 1]);return; }if (g[x]) push(x, x << 1, x << 1 | 1);int mid = l + r >> 1;if (u <= mid) insert(x << 1, l, mid, u, v);else insert(x << 1 | 1, mid + 1, r, u, v);rep(i, 0, 2) f[x][i] = f[x << 1][i] + f[x << 1 | 1][i];}void rotate(int x, int l, int r, int ll, int rr){if (ll <= l && r <= rr){rep(i, 0, 1) swap(f[x][i], f[x][i + 1]);g[x]++; return;}if (g[x]) push(x, x << 1, x << 1 | 1);int mid = l + r >> 1;if (ll <= mid) rotate(x << 1, l, mid, ll, rr);if (rr > mid) rotate(x << 1 | 1, mid + 1, r, ll, rr);rep(i, 0, 2) f[x][i] = f[x << 1][i] + f[x << 1 | 1][i];}bool cmp(int x, int y) { return t[x] < t[y]; }int main(){for (inone(T); T--;){inone(n); t[0] = b[0] = 0;rep(i, 1, n) inone(p[i]);rep(i, 1, n) inone(t[i]), a[i] = b[i] = i;sort(b + 1, b + n + 1, cmp);per(i, n, 1) t[b[i]] = t[b[i]] - t[b[i - 1]];rep(i, 1, n) c[b[i]] = i;sort(a + 1, a + n + 1, cmp);ms(f, 0); ms(g, 0);double W = 0, A = 0;for (int i = 1, j; i <= n; i = j){for (j = i; j <= n&&t[a[i]] == t[a[j]]; j++){insert(1, 1, n, c[a[j]], p[a[j]]);if (c[a[j]] < n) rotate(1, 1, n, c[a[j]] + 1, n);}if (A*(j - 1) < f[1][0]) A = f[1][0] / (j - 1), W = t[a[i]];}printf("%.6lf %.6lf\n", W, A); }return 0;}