HDU 1698 & UESTC 1228 Just a hook

算是线段树中的一道水题了,必须用到懒操作,否则会超时。或者也可以刚开始不计算和,只更新节点,最后算整个线段的颜色和。

 

1.懒操作法

/* 908ms  3448KB  in HDU OJ*/

#include <iostream>

#include <cstdio>

#include <cstring>

#include <cmath>

#include <algorithm>

#include <cstdlib>

using namespace std;

#define N 100011



struct node

{

    int sum;

    int mark;

}tree[4*N];



int n,q;



void build(int l,int r,int rt)

{

    if(l == r)

    {

        tree[rt].sum = 1;

        tree[rt].mark = 0;

        return;

    }

    int mid = (l+r)/2;

    build(l,mid,2*rt);

    build(mid+1,r,2*rt+1);

    tree[rt].sum = tree[2*rt].sum + tree[2*rt+1].sum;

}



void update(int len,int rt)

{

    if(!tree[rt].mark)

        return;

    tree[2*rt].mark = tree[2*rt+1].mark = tree[rt].mark;

    tree[2*rt].sum = tree[2*rt].mark*(len - len/2);

    tree[2*rt+1].sum = tree[2*rt+1].mark*(len/2);

    tree[rt].mark = 0;

}



void change(int l,int r,int aa,int bb,int flag,int rt)

{

    if(aa<=l&&bb>=r)   //不用更新到底部,只要更新到区间

    {

        tree[rt].sum = flag*(r-l+1);

        tree[rt].mark = flag;

        return;

    }

    update(r-l+1,rt);

    int mid = (l+r)/2;

    if(aa<=mid)

        change(l,mid,aa,bb,flag,2*rt);

    if(bb>mid)

        change(mid+1,r,aa,bb,flag,2*rt+1);

    tree[rt].sum = tree[2*rt].sum + tree[2*rt+1].sum;

}



int main()

{

    int t,i;

    int cs = 1;

    int aa,bb,val;

    scanf("%d",&t);

    while(t--)

    {

        memset(tree,0,sizeof(tree));

        scanf("%d%d",&n,&q);

        build(1,n,1);

        for(i=0;i<q;i++)

        {

            scanf("%d%d%d",&aa,&bb,&val);

            change(1,n,aa,bb,val,1);

        }

        printf("Case %d: The total value of the hook is %d.\n",cs++,tree[1].sum);

    }

    return 0;

}
View Code

 

2.最后求和法

#include <iostream>

#include <cstdio>

#include <cstring>

#include <cmath>

#include <cstdlib>

using namespace std;

#define N 100011



struct node

{

    int le,ri;

    int sum;

}tree[4*N];



int n,q;



void build(int l,int r,int rt)

{

    

    tree[rt].sum = 1;

    tree[rt].le = l;

    tree[rt].ri = r;

    if(l == r)

    {

        return;

    }

    int mid = (l+r)/2;

    build(l,mid,2*rt);

    build(mid+1,r,2*rt+1);

}





void change(int l,int r,int aa,int bb,int flag,int rt)

{

    if(aa<=l&&bb>=r)   //不用更新到底部,只要更新到区间

    {

        tree[rt].sum = flag;

        return;

    }

    if(tree[rt].sum != 0)

    {

        tree[2*rt].sum = tree[2*rt+1].sum = tree[rt].sum;

        tree[rt].sum = 0;

    }

    int mid = (l+r)/2;

    if(aa<=mid)

        change(l,mid,aa,bb,flag,2*rt);

    if(bb>mid)

        change(mid+1,r,aa,bb,flag,2*rt+1);

}



int query(int rt)

{

    if(tree[rt].sum != 0)

        return (tree[rt].ri - tree[rt].le + 1)*tree[rt].sum;

    return query(2*rt)+query(2*rt+1);

}



int main()

{

    int t,i;

    int cs = 1;

    int aa,bb,val;

    scanf("%d",&t);

    while(t--)

    {

        memset(tree,0,sizeof(tree));

        scanf("%d%d",&n,&q);

        build(1,n,1);

        for(i=0;i<q;i++)

        {

            scanf("%d%d%d",&aa,&bb,&val);

            change(1,n,aa,bb,val,1);

        }

        printf("Case %d: The total value of the hook is %d.\n",cs++,query(1));

    }

    return 0;

}
View Code

 

 

你可能感兴趣的:(HDU)