2022.3.7
阿新 • • 發佈:2022-03-07
藍書
AcWing 100. IncDec序列
思路:一開始想的是每個數都減去一個數,以為是平均值,後面想到差分就讓每個數減去它前面一個構造了差分陣列,因為我們最終是要讓序列的每一個數都一樣,所以我們讓b[1]=a[1],讓b[2-n]變成0,預處理出2-n的正數和z和負數和f,一部分的操作次數就是現在z和f消去一部分即min(z,f),剩下一部分我們考慮與a[1]相消去,於是答案為min(z,f)+abs(z-f),這裡有abs(z-f)+1種排列方式,+1是因為z和f可能相等,那麼a[1]本身就是一種排列方式了。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; typedef long long ll; const int N=1e5+10,INF=1e8; ll a[N],b[N],n; int main() { scanf("%d", &n); for (int i = 1; i <= n;i++) scanf("%lld",&a[i]); b[1] = a[1]; ll z = 0, f = 0,ans=0; for (int i = 2; i <= n;i++) { b[i] = a[i] - a[i - 1]; if(b[i]>0) z += b[i]; else f -= b[i]; } ans += min(z, f)+abs(z-f); printf("%lld\n%lld", ans, abs(f - z) + 1); return 0; }
AcWing 101. 最高的牛
思路:如果兩頭牛要相互看的見的話它們之間的牛的身高必須都小於他們,於是我們對每次輸入的牛讓它們之間的牛身高都-1,利用差分陣列記錄一下每對牛之間的相對關係,最後轉化成字首和再加上最高的牛的身高。
一開始判重用的是int陣列結果超記憶體了,改用map就過了
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<map> using namespace std; typedef long long ll; const int N=1e4+10,INF=1e8; map<pair<int, int>,int> mp; int ans[N]; int main() { int n, p, h, m; scanf("%d%d%d%d", &n, &p, &h, &m); for (int i = 1; i <= m;i++) { int a, b; scanf("%d%d", &a, &b); if(a>b) swap(a, b); if(mp[{a,b}]) continue; mp[{a,b}] = 1; ans[a + 1]--; ans[b]++; } for (int i = 1; i <= n;i++) { ans[i] +=ans[i-1]; printf("%d\n", ans[i]+h); } return 0; }
AcWing 102. 最佳牛圍欄
思路:要求平均值*1000,應該用浮點數二分,為了簡便計算,對於每個數我們都先減去二分的平均值,這下問題可以轉化成在一個序列中求長度不超過L的非負子段和。因為每塊地最多也就只有2000頭牛,假設每塊地都有2000頭牛的話,那麼二分答案的最大值也就是2000,因此可以縮小二分的範圍,在二分的過程中,我們不必列舉每次的最小值,只需要在i增長的過程中記錄下當前的最小值就可以,同時不斷更新答案:b[i]-mmin。
一開始減平均值的時候想錯了,沒在二分的時候減。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; typedef long long ll; const int N=1e5+10,INF=1e8; int n, m; double a[N], b[N]; int check(double mid) { double mmin = INF, mmax = -INF; for (int i = 1; i <= n;i++) b[i] = b[i - 1] + a[i] - mid; for (int i = m; i <= n;i++) { mmin = min(mmin, b[i - m]); mmax = max(mmax, b[i] - mmin); } return mmax >= 0; } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n;i++) { scanf("%lf", &a[i]); } double l = 0, r = 2000; while(r-l>1e-5) { double mid = (l + r) / 2; if(check(mid)) l = mid; else r = mid; } printf("%d", int(r * 1000)); return 0; }