类型:线段树
题目:给定一个区间,依次对某些区间添加权值,求从右端开始权值最大的点和从左端开始权值最大的点
来源: 113 - ZOJ Monthly, February 2012!!!对于长度为L的区间,有L + 1个点,[0, L]
以[i, i]为叶子节点构造线段树,统计[0, L]的最大值,然后分别从右和左找出第一个与最大值相等的点即可
!!!segmentation fault的原因是将[0, L]分成了L个线段,导致0点无法处理// zoj 3573 Under Attack
// sf sf sf sf wa ac
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAXN = 15009;
const int INF = 1<<30;
int max1;
struct node {
int left, right, mid;
int cover;
}seg_tree[4 * MAXN];
//线段树的建立
void make(int l, int r, int num){
seg_tree[num].left = l;
seg_tree[num].right = r;
seg_tree[num].cover = 0;
seg_tree[num].mid = (l + r) / 2;
if (l < r){
make(l, seg_tree[num].mid, 2 * num);
make(seg_tree[num].mid + 1, r, 2 * num + 1);
}
}
//线段树的插入
void insert(int l, int r, int num, int dep) {
if (seg_tree[num].left == l && seg_tree[num].right == r) {
seg_tree[num].cover += dep;
return;
}
if (r <= seg_tree[num].mid)
insert(l, r, 2 * num, dep);
else if (l > seg_tree[num].mid)
insert(l, r, 2 * num + 1, dep);
else {
insert(l, seg_tree[num].mid, 2 * num, dep);
insert(seg_tree[num].mid + 1, r, 2 * num + 1, dep);
}
}
//线段树的统计操作
int cal(int cover, int num, int l, int r) {
cover += seg_tree[num].cover;
if (seg_tree[num].left == l && seg_tree[num].right == r)
return cover;
if (r <= seg_tree[num].mid)
return cal(cover, 2 * num, l, r);
else
return cal(cover, 2 * num + 1, l, r);
}
int main() {
int len, st, ed, d, i;
while (scanf("%d", &len) != EOF) {
make(0, len, 1);
max1 = -1;
while (scanf("%d %d %d", &st, &ed, &d)) {
if(st == -1)
break;
if(st > ed)
swap(st, ed);
insert(st, ed, 1, d);
}
int i1, i2, temp;
i1 = i2 = -1;
for(i = 0; i <= len; ++i) {
temp = cal(0, 1, i, i);
if(temp > max1) {
max1 = temp;
i1 = i;
}
}
for(i = len; i >= 0; --i) {
temp = cal(0, 1, i, i);
if(temp == max1) {
i2 = i;
break;
}
}
printf("%d %d\n", i1, i2);
}
return 0;
}