问学生分数总和最大为多少
那么就是每道题选的最多的选项为答案,计算即可
如果sum是奇数的一定不行
如果是偶数的话就看一下最大的值是不是比sum的一半小,是YES否NO
因为如果最大比一半还多,说明有一部分需要自己和自己配对
保证奇数个数,很友好
比中位数小的我们就不用管了,因为没有价值
想要保持中位数不断增大就要保证中位数之后的数不小于中位数
所以说,中位数和ai之间的数不断增加到ai+1,直到M用完(看代码理解)
代码:(注意开LL)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| LL T,N,M,K;
vector<LL> a;
int main() { std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin >> N >> M; int x; for(int i = 0;i < N;i++) { cin >> x; a.push_back(x); } sort(a.begin(),a.end()); int mid = N / 2; LL cnt = 1; for(int i = mid+1;i < N;i++) { LL n = cnt * (a[i] - a[mid]); if(n <= M) { a[mid] = a[i]; cnt++; M -= n; } else { int k = M / cnt; a[mid] += k; M = 0; break; } } if(M) { int k = M / cnt; a[mid] += k; M = 0; } cout << a[mid] <<endl; return 0; }
|
题目思路:
我们可以发现,当我们吃完一层的宝藏的时候最后一定停留在最左边的宝藏,或者最右边的宝藏
所以就每次计算出到 i 层的最左和最右的宝藏的路劲进行dp
还可以发现,你去下一层的时候,选的安全列就是你现在位置的左右最近的安全列,这是最优的选择,走远也没有用
所以说,转移一次层数就会有有8条路可以选,枚举这八条路就可以了
L1 -> L2 , L1 -> R2 , R1 -> L2 , R1 -> R2,出发点你可选左或右的安全列,所以 * 2,就是8条
这个算出来的是 i -> i+1层的,然后你再加上1 -> i层的路径,比较找到从1层到达L2和R2的最短路
注意如果这一层没有宝箱就先空着,只算上了一层楼,不转移 L,R
注释很全,可以看注释
因为中间的逻辑错误,改了很久没有找到,令人心痛,不知道写的时候怎么想的,只考虑了当前路径最短,忘了加前面的比较
题目代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
| LL T,N,M,K;
int Left[MAX]; int Right[MAX]; int lsafe[MAX]; int rsafe[MAX]; vector<int> b;
void lsize(int mid,LL *r, LL *l,int i) { LL t1,t2; t1 = abs(mid - lsafe[mid]) + 1; t2 = abs(rsafe[mid] - mid) + 1; *r = min(abs(lsafe[mid] - Left[i] ) + (Right[i] - Left[i]) + t1,abs(rsafe[mid] - Left[i] ) + (Right[i] - Left[i]) + t2); *l = min(abs(lsafe[mid] - Right[i]) + (Right[i] - Left[i]) + t1,abs(rsafe[mid] - Right[i]) + (Right[i] - Left[i]) + t2); } int main() { std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int k,q; cin >> N >> M >> k >> q; int x,y; for(int i = 0;i < k;i++) { cin >> x >> y; if(Left[x] == 0) { Left[x] = Right[x] = y; } else { Left[x] = min(Left[x],y); Right[x] = max(Right[x],y); } } int temp; for(int i = 0;i < q;i++) { cin >> temp; b.push_back(temp); } sort(b.begin(),b.end()); for(int i = 1;i <= M;i++) { auto it = lower_bound(b.begin(),b.end(),i); if(it == b.end()) { rsafe[i] = INF; it--; lsafe[i] = *it; continue; } if(it == b.begin()) { if(*it == i) lsafe[i] = i; else lsafe[i] = -INF; rsafe[i] = *it; continue; } if(*it == i) { lsafe[i] = rsafe[i] = i; } else { rsafe[i] = *it; it--; lsafe[i] = *it; } } LL l,r; int L,R; if(Right[1]) { l = Right[1] - 1 + Right[1] - Left[1]; r = Right[1] - 1; R = Right[1]; L = Left[1]; } else { L = R = 1; l = r = 0; } LL cnt = 0; for(int i = 2;i <= N;i++) { if(!Right[i]) { cnt++; continue; } LL ar,al; lsize(R,&ar,&al,i); LL br,bl; lsize(L,&br,&bl,i); LL tl,tr; tl = l + bl; tl = min(r + al,tl); tr = l + br; tr = min(r + ar,tr); L = Left[i]; R = Right[i]; l = tl + cnt; r = tr + cnt; cnt = 0; } cout << min(r,l) <<endl; return 0; }
|