給定序列\(a\),\(a_i\)能夠傳任意數給\(a_{i + 1}\),要求序列最終嚴格遞增。問是否能夠。ios
能夠貪心作,保證嚴格遞增以後將多餘的數所有傳下去。c++
仔細研究得出結論,最優爲\(\{0, 1, \cdots,n - 1\}\),所以只要保證任意位置的前綴和大於最優序列便可。數組
#includeusing namespace std; #define DEBUG 0 #define int long long #define all(x) x.begin(), x.end() #define sz(x) (int(x.size())) #define vt std::vector #define pb push_back using ll = long long; using db = double; using pii = pair ; using pll = pair ; const int maxn = 1e3 + 50; const int inf = 0x3f3f3f3f3f; template inline void wpr(Args... args) { std::cout << '\n'; } template void wpr(T val, Args... args) { std::cout << val << " "; wpr(args...); } void solve(){ int n, tot = 0, ok = 1; std::cin >> n; for (int i = 0; i < n; ++ i){ int rd; std::cin >> rd; tot += rd; if (tot < (i * (i + 1) / 2)) ok = 0; } std::cout << (ok ? "yes" : "no") << "\n"; } signed main(){ ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int t = 1; std::cin >> t; while (t--) solve(); return 0; }
There are \(n\) houses, you should find some points so that the summary distance from all the houses to the exhibition is minimal. For each case output the number of different positions for the exhibition. Note : the distance is Manhattan Distance .函數
此題考查的是絕對值不等式。spa
當序列長度爲奇數時,顯然中位數爲肯定的,那麼答案只有一個。code
當序列長度爲偶數時,則最小值在\(x\)在範圍\(a_{\frac{n}{2}} \sim a_{\frac{n}{2}-1}\)內皆知足。ci
所以當\(n\)爲偶數時,答案爲\(x,y\)軸可選區間長度的乘積。element
void solve(){ int n; std::cin >> n; vtfx(n), fy(n); for (int i = 0; i < n; ++ i) std::cin >> fx[i] >> fy[i]; sort(all(fx)), sort(all(fy)); if (n & 1) std::cout << 1 << "\n"; else std::cout << 1ll * (fx[n / 2] - fx[n / 2 - 1] + 1) * (fy[n / 2] - fy[n / 2 - 1] + 1) << "\n"; }
Find the position of the maximum element in the array in no more than \(20\) queries. For each query you can ask the position of the second maximum element in a subsegment \(a[l..r]\).get
不難分析出是一個二分題,實際上交互通常都是二分。it
因爲咱們只能詢問第二大的值,咱們首先詢問全局第二大的值並將其設爲端點,而後再二分尋找另外一端點。保證該端點剛好可使得區間內的第二大值爲全局第二大值(也就是該端點爲最大值)。
首先討論最大值在左仍是在右,由於須要討論端點狀況。
inline int query(int l, int r){ std::cout << "? " << l << " " << r << endl; int res; std::cin >> res; return res; } void solve(){ int n; std::cin >> n; int l = 1, r = n; int p = query(l, r); if (p != 1 and p == query(1, p)){ l = 1, r = p; while (l + 1 < r){ int m = l + r >> 1; if (p == query(m, p)) l = m; else r = m; } std::cout << "! " << l << "\n"; }else { l = p, r = n; while (l + 1 < r){ int m = l + r >> 1; if (p == query(p, m)) r = m; else l = m; } std::cout << "! " << r << "\n"; } }
Give you an array \(a\) of length \(n\). Find a subarray \(a[l\cdots r]\) with length at least \(k\) with the largest median. Note: $n\le 2\cdot10^5 $
比賽的時候猜了個結論爲直接使用長度爲\(k\)的滑動窗口,用multiset
維護,遺憾的是猜錯了。
實際上有過一閃而過的想法,利用二分法解決問題,可是苦於沒法找到\(\mathcal{O(n)}\)內能夠完成任務的check
函數。
本題中的中位數能夠理解爲:在一段序列中有超過一半的數大於等於該中位數。本題的官方題解給的是利用前綴和快速求解。
分爲三步:
median
,替換原序列,當元素大於median
時爲1
不然爲-1
。sum
和最小前綴和數組mpre
。由於,序列中位數大於等於median
等價於該序列和前綴和的值大於0.k
,所以能夠利用sum[i] - mpre[i - k] >= 1
判斷以i
爲結尾,長度至少爲k
序列的最大前綴和是否大於 0
。最爲精彩的就是將中位數轉化爲前綴和並進行替換。
int n, k; vtf; inline bool check(int p){ vt a(n + 1), sum(n + 1), mpre(n + 1); for (int i = 1; i <= n; ++ i) a[i] = (f[i - 1] >= p ? 1 : -1); for (int i = 1; i <= n; ++ i){ sum[i] = sum[i - 1] + a[i]; mpre[i] = min(mpre[i - 1], sum[i]); } int ok = 0; for (int i = k; i <= n; ++ i) if (sum[i] - mpre[i - k] >= 1) ok = 1; return ok; } void solve(){ std::cin >> n >> k; f.resize(n); for (int i = 0; i < n; ++ i) std::cin >> f[i]; int l = 1, r = 2e5 + 50; while (l + 1 < r){ int m = l + r >> 1; if (check(m)) l = m; else r = m; } std::cout << l << "\n"; }