diff --git a/src/7/20/T371062s1.cpp b/src/7/20/T371062s1.cpp new file mode 100644 index 0000000..5c6e60d --- /dev/null +++ b/src/7/20/T371062s1.cpp @@ -0,0 +1,53 @@ +#include +#include +#include +#include +#include +#include +using ll = long long; + +ll n,p,q,x,y,ans=std::numeric_limits::max(); +std::string s; + +int main(){ + scanf("%lld%lld%lld%lld%lld",&n,&p,&q,&x,&y); + std::cin>>s; + for(ll msk=0;msk<(1ll< +using namespace std; +typedef long long ll; +const int maxn = 1000010; + +int n; +ll k; +ll a[maxn]; +ll pre[maxn]; +vector d; +int m; +int id[maxn]; + +struct Fenw { + vector c_cnt, c_sum; + int size; + void init(int n) { + size = n; + c_cnt.assign(n+1, 0); + c_sum.assign(n+1, 0); + } + void add_cnt(int i, ll v) { + for (; i <= size; i += i & -i) + c_cnt[i] += v; + } + void add_sum(int i, ll v) { + for (; i <= size; i += i & -i) + c_sum[i] += v; + } + ll query_cnt(int i) { + if (i <= 0) return 0; + ll res = 0; + for (; i; i -= i & -i) + res += c_cnt[i]; + return res; + } + ll query_sum(int i) { + if (i <= 0) return 0; + ll res = 0; + for (; i; i -= i & -i) + res += c_sum[i]; + return res; + } +} fenw; + +void discrete() { + d.clear(); + for (int i = 0; i <= n; i++) + d.push_back(pre[i]); + sort(d.begin(), d.end()); + d.erase(unique(d.begin(), d.end()), d.end()); + m = d.size(); + for (int i = 0; i <= n; i++) { + id[i] = lower_bound(d.begin(), d.end(), pre[i]) - d.begin() + 1; + } +} + +ll count_func(ll X) { + fenw.init(m); + for (int i = 1; i <= n; i++) { + fenw.add_cnt(id[i], 1); + } + int j = 0; + ll cnt_total = 0; + for (int l = 1; l <= n; l++) { + ll key = pre[l-1] + X; + while (j < m && d[j] <= key) + j++; + if (j > 0) { + ll cnt1 = fenw.query_cnt(j); + cnt_total += cnt1; + } + fenw.add_cnt(id[l], -1); + } + return cnt_total; +} + +pair count_sum_func(ll X) { + fenw.init(m); + for (int i = 1; i <= n; i++) { + fenw.add_cnt(id[i], 1); + fenw.add_sum(id[i], pre[i]); + } + int j = 0; + ll cnt_total = 0; + ll sum_total = 0; + for (int l = 1; l <= n; l++) { + ll key = pre[l-1] + X; + while (j < m && d[j] <= key) + j++; + if (j > 0) { + ll cnt1 = fenw.query_cnt(j); + ll sum1 = fenw.query_sum(j); + cnt_total += cnt1; + sum_total += (sum1 - pre[l-1] * cnt1); + } + fenw.add_cnt(id[l], -1); + fenw.add_sum(id[l], -pre[l]); + } + return {cnt_total, sum_total}; +} + +int main() { + scanf("%d%lld", &n, &k); + for (int i = 1; i <= n; i++) { + scanf("%lld", &a[i]); + } + pre[0] = 0; + for (int i = 1; i <= n; i++) { + pre[i] = pre[i-1] + a[i]; + } + discrete(); + + ll L = 0, R = pre[n]; + while (L < R) { + ll mid = (L + R) >> 1; + if (count_func(mid) >= k) { + R = mid; + } else { + L = mid + 1; + } + } + ll X0 = L; + pair res; + if (X0 - 1 < 0) { + res = {0, 0}; + } else { + res = count_sum_func(X0 - 1); + } + ll cnt_less = res.first; + ll sum_less = res.second; + ll cnt_equal = k - cnt_less; + ll ans = sum_less + cnt_equal * X0; + printf("%lld\n", ans); + return 0; +} +``` + +### 代码解释 +1. **前缀和计算**:首先计算数组`a`的前缀和数组`pre`,用于快速计算任意子段和。 +2. **离散化**:将前缀和数组`pre`中的值排序并去重,生成离散化数组`d`,并建立映射`id`,将原前缀和值映射到离散化后的下标。 +3. **二分查找第k小的子段和**: + - 使用`count_func(X)`函数统计子段和不超过`X`的个数。该函数利用树状数组高效维护当前右端点前缀和,并通过移动指针`j`避免重复二分查找。 + - 通过二分调整`X`的值,直到找到满足条件的最小`X0`,使得子段和不超过`X0`的个数至少为`k`。 +4. **计算前k小子段和的和**: + - 使用`count_sum_func(X0-1)`计算所有小于`X0`的子段和的总和`sum_less`及个数`cnt_less`。 + - 剩余的子段和均为`X0`,个数为`k - cnt_less`。 + - 最终结果为`sum_less + (k - cnt_less) * X0`。 + +该方法高效地利用了二分答案和树状数组,结合离散化处理,确保在较大数据规模下仍能在合理时间内求解。 \ No newline at end of file diff --git a/src/7/20/T635780fix.cpp b/src/7/20/T635780fix.cpp new file mode 100644 index 0000000..294989d --- /dev/null +++ b/src/7/20/T635780fix.cpp @@ -0,0 +1,3 @@ +int main(){ + +} \ No newline at end of file diff --git a/src/test.cpp b/src/test.cpp index 37f2db2..294989d 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -1,4 +1,3 @@ -#include int main(){ - printf("[%10.c]\n",'^'); + } \ No newline at end of file