#386. 【UNR #3】鸽子固定器
?#386. 【UNR #3】鴿子固定器
題目鏈接
官方題解
分析:
神奇的做法+鏈表。
首先按照大小排序。
對于小于選擇小于m個物品的時候,這個m個物品一定是一段連續的區間。因為,如果中間空著一個物品沒選,而有沒選到m個,還可以再選,于是選上空著的,不會增加花費,還增加了價值,所以可以直接枚舉一個左端點,一個右端點,確定所有長度小于等于m個區間,然后計算即可。
如果等于m個物品,在上面的區間上可能不是連續的了。于是我們考慮選的這m個物品中的牢固度最小的x,然后再選m-1的物品(牢固度)比它大的。此時,我們把小于它的可以忽略了,假設當前的序列是上面拍完序后只保留了大于這個物品的牢固度的物品。然后在此序列上這m個物品又是一段連續的區間,(x的位置向左m個,向右m個,在此的一段連續的區間)。
選的方案如下圖,區間為先按大小排好序,然后去掉牢固度比x小的物品,m個物品的牢固度都比x大,選的方案就是藍色部分:
如果不是一段連續的區間:
四種情況,如果是藍色的情況,那么選中間空著的一定比選x優,牢固度大于x(超出m的部分也是大于x的,小于x的去掉了)
如果是綠色的情況,x作為端點,發現,如果選空著的,牢固度不僅大于x,而且,區間長度還會縮小,也就是大小的極差也會減小,所以x無法被選上。
所以對于必須且且最小值是x的,選的m個物品,必須是以x為中心,向左向右連續的一段區間。
所以我們可以依次從小到大枚舉x,然后用鏈表維護刪除的過程,那么剩下的物品就是一定大于x的。然后枚舉這m個區間,就可以了。
代碼:
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<cmath> 5 #include<iostream> 6 #include<cctype> 7 #include<set> 8 #include<vector> 9 #include<queue> 10 #include<map> 11 using namespace std; 12 typedef long long LL; 13 14 inline int read() { 15 int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; 16 for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f; 17 } 18 19 const int N = 200100; 20 21 struct Node{ 22 int s, v, id; 23 }A[N], B[N], C[N]; 24 int L[N], R[N]; 25 LL s[N]; 26 int ds, dv; 27 28 bool cmp1(Node A, Node B) { 29 return A.s < B.s; 30 } 31 bool cmp2(Node A, Node B) { 32 return A.v < B.v; 33 } 34 LL Calc(LL v, LL s) { 35 if (dv == 2) v = 1ll * v * v; 36 if (ds == 2) s = 1ll * s * s; 37 return v - s; 38 } 39 void del(int p) { 40 R[L[p]] = R[p]; 41 L[R[p]] = L[p]; 42 } 43 int main() { 44 int n = read(), m = read(); ds = read(), dv = read(); 45 for (int i=1; i<=n; ++i) A[i].s = read(), A[i].v = read(); 46 sort(A + 1, A + n + 1, cmp1); //--- 47 for (int i=1; i<=n; ++i) A[i].id = i, B[i] = A[i]; 48 LL Ans = 0; 49 for (int i=1; i<=n; ++i) { 50 LL sum = 0; 51 for (int j=i; j<=(i+m-1)&&j<=n; ++j) { 52 sum += A[j].v; 53 Ans = max(Ans, Calc(sum, A[j].s - A[i].s)); 54 } 55 } 56 sort(A + 1, A + n + 1, cmp2); 57 for (int i=1; i<=n; ++i) L[i] = i - 1, R[i] = i + 1; 58 L[n + 1] = n, R[0] = 1; 59 60 for (int i=1; i<=n; ++i) { 61 int p = 0; 62 for (int j=A[i].id,k=1; j>=1&&k<=m; j=L[j],++k) C[++p] = B[j]; 63 reverse(C + 1, C + p + 1); 64 for (int j=R[A[i].id],k=2; j<=n&&k<=m; j=R[j],++k) C[++p] = B[j]; 65 for (int j=1; j<=p; ++j) s[j] = s[j - 1] + C[j].v; 66 for (int j=m; j<=p; ++j) 67 Ans = max(Ans, Calc(s[j] - s[j - m], C[j].s - C[j - m + 1].s)); 68 del(A[i].id); 69 } 70 cout << Ans; 71 return 0; 72 }?
轉載于:https://www.cnblogs.com/mjtcn/p/9628329.html
總結
以上是生活随笔為你收集整理的#386. 【UNR #3】鸽子固定器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Interface Collector
- 下一篇: 服务管理-文件服务器