L3-017 森森快递
一开始的做法
考虑不全面
线段树+贪心
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 10;
typedef struct node{
int l, r;
ll minn;
bool operator < (const node x) const {
if(x.r != r)
return x.r > r;
else
return x.l < l;
}
}node;
node tree[maxn<<2];
node ans[maxn];
ll minn;
void build(int k, int l, int r){
tree[k].l = l, tree[k].r = r;
if(l == r){
scanf("%lld", &tree[k].minn);
return;
}
int mid = (l+r)>>1;
build(k<<1, l, mid);
build(k<<1|1, mid+1, r);
tree[k].minn = min(tree[k<<1].minn, tree[k<<1|1].minn);
}
void query(int k, int l, int r, int cl, int cr){
if(l >= cl && r <= cr){
minn = min(minn, tree[k].minn);
return;
}
int mid = (l+r)>>1;
if(cl <= mid) query(k<<1, l, mid, cl, cr);
if(cr > mid) query(k<<1|1, mid+1, r, cl ,cr);
}
void swap(int &x, int &y){
int t = x; x = y; y = t;
}
int n, q;
int main(){
int a, b;
scanf("%d %d", &n, &q);
build(1, 1, n-1);
for(int i = 0; i < q; ++ i){
scanf("%d %d", &a, &b);
if(a > b) swap(a, b);
ans[i].l = a+1;
ans[i].r = b;
minn = 1e18;
query(1, 1, n-1, a+1, b);
ans[i].minn = minn;
}
sort(ans, ans+q);
ll sum = 0;
int e = 0;
// 5 2
// 5 10 10 5
// 0 3
// 1 4
// 输出 5
// 实际是 10
// 所有必须更新
for(int i = 0; i < q; ++ i){
if(ans[i].l > e){
if(e == ans[i].r)//多个4 5就会出问题
continue;
sum += ans[i].minn;
e = ans[i].r;
}
}
printf("%lld\n", sum);
return 0;
}
AC代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 10;
typedef struct node{
int l, r;
ll minn, f;
bool operator < (const node x) const {
if(x.r != r)
return x.r > r;
else
return x.l < l;
}
}node;
node tree[maxn<<2];
node ans[maxn];
ll minn;
void down(int k){
if(tree[k].f){
tree[k<<1].f += tree[k].f;
tree[k<<1|1].f += tree[k].f;
tree[k<<1].minn -= tree[k].f;
tree[k<<1|1].minn -= tree[k].f;
tree[k].f = 0;
}
}
void build(int k, int l, int r){
tree[k].l = l, tree[k].r = r;
if(l == r){
scanf("%lld", &tree[k].minn);
return;
}
int mid = (l+r)>>1;
build(k<<1, l, mid);
build(k<<1|1, mid+1, r);
tree[k].minn = min(tree[k<<1].minn, tree[k<<1|1].minn);
}
void query(int k, int l, int r, int cl, int cr){
if(l >= cl && r <= cr){
minn = min(minn, tree[k].minn);
return;
}
down(k);
int mid = (l+r)>>1;
if(cl <= mid) query(k<<1, l, mid, cl, cr);
if(cr > mid) query(k<<1|1, mid+1, r, cl ,cr);
}
void swap(int &x, int &y){
int t = x; x = y; y = t;
}
void updata(int k, int l, int r, int cl, int cr, ll c){
if(l >= cl && r <= cr){
tree[k].f += c;
tree[k].minn -= c;
return;
}
down(k);
int mid = (l+r)>>1;
if(cl <= mid) updata(k<<1, l, mid, cl, cr, c);
if(cr > mid) updata(k<<1|1, mid+1, r, cl, cr, c);
tree[k].minn = min(tree[k<<1].minn, tree[k<<1|1].minn);
}
int n, q;
int main(){
int a, b;
scanf("%d %d", &n, &q);
build(1, 1, n-1);
for(int i = 0; i < q; ++ i){
scanf("%d %d", &a, &b);
if(a > b) swap(a, b);
ans[i].l = a+1;
ans[i].r = b;
}
sort(ans, ans+q);
ll sum = 0;
for(int i = 0; i < q; ++ i){
minn = 1e18;
query(1, 1, n-1, ans[i].l, ans[i].r);
sum += minn;
updata(1, 1, n-1, ans[i].l, ans[i].r, minn);
}
printf("%lld\n", sum);
return 0;
}