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;
}
posted @ 2020-07-23 22:20  wansheking  阅读(96)  评论(0)    收藏  举报