Fork me on GitHub

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

 

 

posted @ 2013-12-24 19:55  whatbeg  阅读(245)  评论(0编辑  收藏  举报