LGP3602 Koishi Loves Segments
分析
类似反悔贪心吧......就是你排一下序,然后动态维护......做完了!所以, mhh \operatorname{mhh} mhh 是对的拜谢
正解
cpp
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2000005;
int n, m;
struct node1{
int l, r;
}a[N];
bool operator < (const node1 &tmp1, const node1 &tmp2){
return tmp1.l < tmp2.l;
}
struct node2{
int p, x;
}b[N];
bool operator < (const node2 &tmp1, const node2 &tmp2){
return tmp1.p < tmp2.p;
}
multiset<int> s;
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> m;
for (int i = 1; i <= n; i++){
cin >> a[i].l >> a[i].r;
}
sort(a + 1, a + n + 1);
for (int i = 1; i <= m; i++){
cin >> b[i].p >> b[i].x;
}
sort(b + 1, b + m + 1);
int ans = n;
for (int i = 1, j = 1; i <= m; i++){
while (j <= n && a[j].l <= b[i].p){
s.insert(a[j++].r);
}
while (!s.empty() && *s.begin() < b[i].p){
s.erase(s.begin());
}
while ((long long)s.size() > b[i].x){
s.erase(--s.end());
ans--;
}
}
cout << ans;
return 0;
}
LGP3466 POI 2008 KLO-Building blocks
原题链接:POI 2008 KLO-Building blocks
分析
就是,我们其实可以枚举,然后在线段树上找......别急,这是对的吗?
那你要是这样的话,其实只是把 O ( m n ) O(mn) O(mn) 降到了 O ( n 2 ) O(n^2) O(n2),优化不多......
怎么贪呢......换句话说,我要找到一个 x x x,使得 x × k − ∑ j = i i + k h j x\times k-\sum\limits_{j=i}^{i+k}h_j x×k−j=i∑i+khj 最小......那不是平均数具有很大的优势吗?为啥是中位数😭

那可以直接写了吧......拿一个主席树就行了......
正解
cpp
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 100005, M = 1000005;
int n, k, h[N];
struct tree{
int p, ls, rs, val;
}tr[N << 5];
int tot;
int rt[N];
struct president_tree{
void pushup(int p){
tr[p].p = tr[tr[p].ls].p + tr[tr[p].rs].p;
tr[p].val = tr[tr[p].ls].val + tr[tr[p].rs].val;
return ;
}
void modify(int p, int pre, int l, int r, int s){
if (l == r){
tr[p].p = tr[pre].p + 1;
tr[p].val = tr[pre].val + s;
return ;
}
int mid = (l + r) >> 1;
if (s <= mid){
tr[p].ls = ++tot;
tr[p].rs = tr[pre].rs;
modify(tr[p].ls, tr[pre].ls, l, mid, s);
}
else{
tr[p].ls = tr[pre].ls;
tr[p].rs = ++tot;
modify(tr[p].rs, tr[pre].rs, mid + 1, r, s);
}
pushup(p);
}
int query_kth(int pre, int p, int l, int r, int k){
if (l == r)
return l;
int mid = (l + r) >> 1;
int tmp = tr[tr[p].ls].p - tr[tr[pre].ls].p;
if (tmp >= k){
return query_kth(tr[pre].ls, tr[p].ls, l, mid, k);
}
else{
return query_kth(tr[pre].rs, tr[p].rs, mid + 1, r, k - tmp);
}
}
int query(int pre, int p, int l, int r, int k){
if (l == r){
return min(k, tr[p].p - tr[pre].p) * l;
}
int mid = (l + r) >> 1;
int tmp = tr[tr[p].ls].p - tr[tr[pre].ls].p;
if (tmp >= k){
return query(tr[pre].ls, tr[p].ls, l, mid, k);
}
else{
return tr[tr[p].ls].val - tr[tr[pre].ls].val + query(tr[pre].rs, tr[p].rs, mid + 1, r, k - tmp);
}
}
}T;
int sum[N], total;
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> k;
for (int i = 1; i < k; i++){
cin >> h[i];
rt[i] = ++tot;
total += h[i];
T.modify(rt[i], rt[i - 1], 0, 1000000, h[i]);
}
int ans = 0x3f3f3f3f3f3f3f3f;
int pos = 0, val = 0;
for (int i = k; i <= n; i++){
cin >> h[i];
rt[i] = ++tot;
total += h[i] - h[i - k];
T.modify(rt[i], rt[i - 1], 0, 1000000, h[i]);
int p = (k + 1) >> 1;
int tmp = T.query_kth(rt[i - k], rt[i], 0, 1000000, p);
int res = T.query(rt[i - k], rt[i], 0, 1000000, p);
res = total - 2 * res - (k - p) * tmp + p * tmp;
if (res < ans){
ans = res;
pos = i;
val = tmp;
}
}
cout << ans << '\n';
for (int i = 1; i <= n; i++){
if (pos < i + k && pos >= i){
cout << val << '\n';
}
else{
cout << h[i] << '\n';
}
}
}
千万不要写错 ans 的初值!!!