FZU - 1608 - Huge Mission (区间更新+贪心)

版权声明:Andy https://blog.csdn.net/Alibaba_lhl/article/details/81946933

 Sample Input

24 4 
0 8 1 
8 12 10 
12 20 8 
20 24 5 
4 3 
0 3 1 
1 2 2 
2 4 5 
10 10
8 9 15
1 7 5
5 10 3
0 7 6
5 8 2
3 7 3
2 9 12
7 8 14
6 7 2
5 6 16

Sample Output

132 
13
108

Source::Click here

自己刚接触线段树,对线段树只是稍微理解了一点,先写了模板题。自己再悟悟吧,然后再写一个较为清晰的code.

#include<cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 5e4+10;

struct NODE
{
    int l, r;
    int value;//维护当前区间的(工作效率)最大值
}tree[MAXN<<2];

void build_tree(int rt, int l, int r)//建树
{
    tree[rt].l = l;
    tree[rt].r = r;
    tree[rt].value = 0;
    if(l+1==r) return ;//区间长度为1时,结束递归
    int mid = (l+r)>>1;
    build_tree(rt<<1,l,mid);//左儿子(注意左右儿子区间分别为[l, mid] 和 [mid, r])
    build_tree(rt<<1|1,mid,r);//右儿子
}
void update(int rt, int l, int r, int v)//这个函数才用了贪心的思想
{
    if(tree[rt].l>r || tree[rt].r<l) return ;//若该节点所在区间没有与[l,r]
    if(tree[rt].l>=l && tree[rt].r<=r)//若该节点所在区间全包含在[l,r]内
    {
        tree[rt].value = max(tree[rt].value,v);
        return ;
    }
    update(rt<<1,l,r,v);//继续向下更新左儿子
    update(rt<<1|1,l,r,v);//继续向下更新右儿子
}
int query(int rt, int l, int r)
{
    if(l+1==r) return tree[rt].value;
    tree[rt<<1].value = max(tree[rt<<1].value,tree[rt].value);
    tree[rt<<1|1].value = max(tree[rt<<1|1].value,tree[rt].value);
    int mid = (l+r)>>1;
    return query(rt<<1,l,mid) + query(rt<<1|1,mid,r);
}
int n, m;
int main()
{
    while(~scanf("%d %d",&n,&m))
    {
        memset(tree,0,sizeof(tree));
        build_tree(1,0,n);
        while(m--)
        {
            int s, t, p;
            scanf("%d %d %d",&s,&t,&p);
            update(1,s,t,p);
        }
        printf("%d\n",query(1,0,n));
    }
}

下面的代码的查询函数较容易理解一点吧! 

#include<cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 5e4+3000;

struct NODE
{
    int l, r;
    int value;//维护当前区间的(工作效率)最大值
}tree[MAXN<<2];

void build_tree(int rt, int l, int r)//建树
{
    tree[rt].l = l;
    tree[rt].r = r;
    tree[rt].value = 0;
    if(l+1==r) return ;//区间长度为1时,结束递归
    int mid = (l+r)>>1;
    build_tree(rt<<1,l,mid);//左儿子(注意左右儿子区间分别为[l, mid] 和 [mid, r])
    build_tree(rt<<1|1,mid,r);//右儿子
}
void update(int rt, int l, int r, int v)//这个函数才用了贪心的思想
{
    if(tree[rt].l>r || tree[rt].r<l) return ;//若该节点所在区间没有与[l,r]
    if(tree[rt].l>=l && tree[rt].r<=r)//若该节点所在区间全包含在[l,r]内
    {
        tree[rt].value = max(tree[rt].value,v);
        return ;
    }
    update(rt<<1,l,r,v);//继续向下更新左儿子
    update(rt<<1|1,l,r,v);//继续向下更新右儿子
}
ll sum;
void query(int rt, int l, int r)
{
    if(l+1==r)
    {
        sum += tree[rt].value;
        return ;
    }
    tree[rt<<1].value = max(tree[rt<<1].value,tree[rt].value);
    tree[rt<<1|1].value = max(tree[rt<<1|1].value,tree[rt].value);
    int mid = (l+r)>>1;
    query(rt<<1,l,mid);
    query(rt<<1|1,mid,r);
}
int n, m;
int main()
{
    while(~scanf("%d %d",&n,&m))
    {
        memset(tree,0,sizeof(tree));
        build_tree(1,0,n);
        while(m--)
        {
            int s, t, p;
            scanf("%d %d %d",&s,&t,&p);
            update(1,s,t,p);
        }
        sum = 0;
        query(1,0,n);
        printf("%lld\n",sum);
    }
}

猜你喜欢

转载自blog.csdn.net/Alibaba_lhl/article/details/81946933