题意:
给定M个区间 (1 <= M <= 500000)和这些区间上的权值,求最终并区间的最
大权值总和(某个区间不能被计算两次)。
http://acm.fzu.edu.cn/problem.php?pid=1608
思路:
大权值一定会取代小权值,所以可以先将所有线段按权值排序,更新的时候后面的直接覆盖前面的即可。
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int maxn = 50000+5;
const int maxm = 500000+5;
using namespace std;
int Tree[maxn*4], lazy[maxn*4];
struct Node{
int l, r, e;
bool operator < (const Node& rhs) const{
return e < rhs.e;
}
}nodes[maxm];
void push_up(int root){
Tree[root] = Tree[root<<1] + Tree[root<<1 | 1];
}
void push_down(int root, int len){
if(0 == lazy[root]) return;
lazy[root<<1] = lazy[root];
lazy[root<<1 | 1] = lazy[root];
Tree[root<<1] = lazy[root<<1] * (len-(len>>1));
Tree[root<<1 | 1] = lazy[root<<1 | 1] * (len>>1);
lazy[root] = 0;
}
void update(int la, int rb, int l, int r, int root, int val){
if(la > r||l > rb) return;
if(la <= l&&rb >= r){
Tree[root] = (r-l+1)*val;
lazy[root] = val;
return;
}
push_down(root, r-l+1);
int mid = (l+r) >> 1;
if(la <= mid)
update(la, rb, l, mid, root<<1, val);
if(rb > mid)
update(la, rb, mid+1, r, root<<1 | 1, val);
push_up(root);
}
int main()
{
freopen("in.txt","r",stdin);
int n, m;
while(scanf("%d%d",&n,&m) == 2){
memset(Tree, 0, sizeof(Tree));
memset(lazy, 0, sizeof(lazy));
for(int i = 1; i <= m; ++i) scanf("%d%d%d", &nodes[i].l, &nodes[i].r, &nodes[i].e);
sort(nodes+1, nodes+m+1);
for(int i = 1; i <= m; ++i){
update(nodes[i].l+1, nodes[i].r, 1, n, 1, nodes[i].e);
}
printf("%d\n", Tree[1]);
}
fclose(stdin);
return 0;
}