题目给出一个长度为n的数列,要求把这些数重新排序,使得 |a1−a2| ≤ | a2−a3 | ≤ … ≤ | an−1−an | ,其实把数组按大小排序,可以知道
相距越远的两个数,两者的差越大,所以我们可以通过前后循环获取数,这样得到的数列,每两数之间的差则是逐渐减小的,所以最后倒着输出就行,
当时憨憨,直接输出了。
#include <cstdio> #include <iostream> #include <algorithm> #include <cmath> #include <string> #include <cstring> using namespace std; const long long N = 1e10 + 7; const int maxn = 1e5 + 5; const long long INF = 8e18; typedef long long ll; #define for0(i,n) for(int i = 0;i < n;i++) #define for1(i,n) for(int i = 1;i <= n;i++) using namespace std; int x[maxn],b[maxn]; int main() { int t; cin >> t; while(t--){ int n,j = 0; cin >> n; for1(i,n){ cin >> x[i]; } sort(x+1,x+1+n); for(int i = 1;i <= n/2;i++){ b[j++] = x[i]; b[j++] = x[n-i+1]; } if(n%2) b[j++] = x[n/2+1]; for(int i = n-1;i >= 0;i--){ cout << b[i] << " "; } cout << endl; } return 0; }
这道题就行寻找一个最小秒数 x ,可以通过在第m秒时( 1 <= m <= x )在数组中选择任意数加上2(m-1) ,最后这个数列变为一个不减序列。
当数列本身就是不减序列时,当然x就等于0,而出现减小情况时,这时就肯定会存在一个最高端和最低端,当这个高度差都可弥补时,其他的高度差
当然也可填补,因为每一秒时可以任意选择哪些数加获不加。所以主要就是来寻找最高端和最低端的高度差(1 + 21 + 22 + + 2x 这个数要大于等于这个高度差)。
#include <cstdio> #include <iostream> #include <algorithm> #include <cmath> #include <string> #include <cstring> #include <map> using namespace std; const long long N = 1e10 + 7; const int maxn = 1e5 + 5; const long long INF = 8e18; typedef long long ll; #define for0(i,n) for(int i = 0;i < n;i++) #define for1(i,n) for(int i = 1;i <= n;i++) ll x[100100]; int main() { int t; cin >> t; while(t--){ int n; cin >> n; ll maxnum = -N ,sum = 0,time = 0,m = 0; for(int i = 0;i < n;i++){ cin >> x[i]; } for(int i = 0;i < n;i++){ maxnum = max(maxnum,x[i]); m = max(m,maxnum - x[i]); } while(m - sum > 0){ sum += pow(2,time++); } cout << time << endl; } return 0; }
给出 n 个人的财富,并给出一个富人标准 x ,你可以收取一些人的钱然后平均分给这些被收取钱财的人手中,问最多可以创造多少名富人。
这个题一想就是先收有钱人的钱财,然后平分,不断更新富人数,当出现平均值低于富人标准时,往后便永远不会出现新答案。
#include <cstdio> #include <iostream> #include <algorithm> #include <cmath> #include <string> #include <cstring> using namespace std; const long long N = 1e10 + 7; const int maxn = 2e5 + 5; const long long INF = 8e18; typedef long long ll; #define for0(i,n) for(int i = 0;i < n;i++) #define for1(i,n) for(int i = 1;i <= n;i++) ll sum[100100]; int a[100100]; int main() { int t; cin >> t; while(t--){ int i,n,x,num = 0; cin >> n >> x; for(i = 1;i <= n;i++){ cin >> a[i]; } sort(a+1,a+n+1,greater<int>()); for( i = 1;i <= n;i++){ sum[i] = sum[i-1] + a[i]; if(sum[i] * 1.0 / i < x) break; } cout << i - 1 << endl; } return 0; }
给出n个怪物(围成一圈)的血量和爆炸伤害,其中你可以用一颗子弹打掉一个怪物一滴血,当一个怪物死掉时,便发生爆炸,使得下一个怪物血量减少。问最少消耗的子弹数。这时可以找到选择的起始点不同,最后消耗的子弹也会不同,但每当起始点确定,肯定都是向一个方向进行,所以可以预先处理一下每个怪若被前一个怪炸掉后的血量(差分)这样可以得到一个全部怪被前一个怪炸的血量和,然而当选择一个怪物时这个怪不会被炸,所以再加上他之前怪的损伤,就得到答案。
#include <cstdio> #include <iostream> #include <algorithm> #include <cmath> #include <string> #include <cstring> #include <map> using namespace std; const long long N = 1e18 + 7; const int maxn = 1e5 + 5; const long long INF = 8e18; typedef long long ll; #define for0(i,n) for(int i = 0;i < n;i++) #define for1(i,n) for(int i = 1;i <= n;i++) ll a[300100],b[300100],num[300100]; int main() { int t; cin >> t; while(t--){ int n; ll sum = 0,minnum = N; cin >> n; for0(i,n){ scanf("%lld%lld",&a[i],&b[i]); } for0(i,n){ if(i == 0) num[i] = max( (ll)0,a[i] - b[n-1]); else{ num[i] = max( (ll)0,a[i] - b[i-1] ); } sum += num[i]; } for(int i = 0;i < n;i++){ minnum = min( minnum,sum + (a[i] - num[i]) ); } printf("%lld\n",minnum); } return 0; }
原文:https://www.cnblogs.com/emhhbw/p/12989758.html