HDU 1698 Just a Hook 线段树成段更新

来源:互联网 发布:单片机与plc的区别 编辑:程序博客网 时间:2024/06/05 06:43

算是我真正意义上的区间更新的第一题,我是这样理解区间更新的:

为了节省时间,在更新区间的时候不必每次都更新到叶子节点。如果当前节点的的区间被包含在查询区间内,就暂时只更新这个节点。但是如果仅仅这样,将来在下次更新的时候,如果涉及了该节点的孩子节点,就会出错。

所以有一个办法:在更新的时候,如果我们明确知道了该节点的儿子节点涉及到了将要更新的区间,就事先把它的左右儿子节点按照父节点的val更新了,由于更新是递归实现的,所以如果它的孙子节点也涉及了,孙子节点会在儿子节点的递归层被更新。

这样做肯定比每次都更新到叶子节点大大节省了时间。

AC代码:

/* ***********************************************Author        :angon************************************************ */#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <stack>#include <vector>#include <queue>#include <set>#include <map>#include <string>#include <math.h>#include <stdlib.h>#include <time.h>using namespace std;#define REP(i,k,n) for(int i=k;i<n;i++)#define REPP(i,k,n) for(int i=k;i<=n;i++)#define scan(d) scanf("%d",&d)#define scann(n,m) scanf("%d%d",&n,&m)#define mst(a,k)  memset(a,k,sizeof(a));#define LL long long#define maxn 100005#define mod 100000007/*inline int read(){    int s=0;    char ch=getchar();    for(; ch<'0'||ch>'9'; ch=getchar());    for(; ch>='0'&&ch<='9'; ch=getchar())s=s*10+ch-'0';    return s;}inline void print(int x){    if(!x)return;    print(x/10);    putchar(x%10+'0');}*/int n;struct node{    int l,r,v,sum; //v 代表类型,sum代表总和}seg[maxn*4];void build(int i,int l,int r){    seg[i].l=l;    seg[i].r=r;    seg[i].v=1;    if(l==r)    {        seg[i].sum=1;        return ;    }    int mid=(l+r)>>1;    build(i<<1,l,mid);    build(i<<1|1,mid+1,r);    seg[i].sum=seg[i<<1].sum+seg[i<<1|1].sum;}void update(int i,int l,int r,int val){    if(seg[i].v==val) return ; //剪枝    if(l<=seg[i].l && r>=seg[i].r)    {        seg[i].v=val;        seg[i].sum=(seg[i].r-seg[i].l+1)*val;        return ;    }    if(seg[i].v>0)    //如果大于0,说明区间里面颜色一样    {               //由上面一个if没有return可知后面必定对子树进行操作,        seg[i<<1].v=seg[i<<1|1].v=seg[i].v;    //所以先更新孩子节点        seg[i<<1].sum=(seg[i<<1].r-seg[i<<1].l+1)*seg[i].v;        seg[i<<1|1].sum=(seg[i<<1|1].r-seg[i<<1|1].l+1)*seg[i].v;        seg[i].v=0;    }    int mid=(seg[i].l+seg[i].r)>>1;    if(l<=mid) update(i<<1,l,r,val);    if(r>mid) update(i<<1|1,l,r,val);    seg[i].sum=seg[i<<1].sum+seg[i<<1|1].sum;}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    int t,q,x,y,c;    scan(t);    int cas=1;    while(t--)    {        scan(n);        build(1,1,n);        scan(q);        while(q--)        {            scanf("%d%d%d",&x,&y,&c);            update(1,x,y,c);        }        printf("Case %d: The total value of the hook is %d.\n",cas++,seg[1].sum);    }    return 0;}

附kuangbin大神的代码,更加符合标准,更模版化,再看一遍也许可以帮助理解

/*HDU 1689线段树成段更新*/#include<stdio.h>#include<string.h>#include<algorithm>#include<iostream>using namespace std;const int MAXN=100010;struct Node{    int l,r;    int lazy,tag;    int sum;}segTree[MAXN*3];void Build(int i,int l,int r){    segTree[i].l=l;    segTree[i].r=r;    segTree[i].lazy=0;    segTree[i].tag=0;    if(l==r)    {        segTree[i].sum=1;        return;    }    int mid=(l+r)>>1;    Build(i<<1,l,mid);    Build((i<<1)|1,mid+1,r);    segTree[i].sum=segTree[i<<1].sum+segTree[(i<<1)|1].sum;}void update(int i,int l,int r,int v){    if(segTree[i].l==l&&segTree[i].r==r)//成段更新    {        segTree[i].lazy=1;        segTree[i].tag=v;        segTree[i].sum=(r-l+1)*v;        return;    }    int mid=(segTree[i].l+segTree[i].r)>>1;    if(segTree[i].lazy==1)    {        segTree[i].lazy=0;        update(i<<1,segTree[i].l,mid,segTree[i].tag);        update((i<<1)|1,mid+1,segTree[i].r,segTree[i].tag);        segTree[i].tag=0;    }    if(r<=mid) update(i<<1,l,r,v);    else if(l>mid)update((i<<1)|1,l,r,v);    else    {        update(i<<1,l,mid,v);        update((i<<1)|1,mid+1,r,v);    }    segTree[i].sum=segTree[i<<1].sum+segTree[(i<<1)|1].sum;}int main(){      //  freopen("in.txt","r",stdin); //  freopen("out.txt","w",stdout);    int x,y,z;    int n;    int m;    int T;    scanf("%d",&T);    int iCase=0;    while(T--)    {        iCase++;        scanf("%d%d",&n,&m);        Build(1,1,n);        while(m--)        {            scanf("%d%d%d",&x,&y,&z);            update(1,x,y,z);        }        printf("Case %d: The total value of the hook is %d.\n",iCase,segTree[1].sum);    }    return 0;}


0 0
原创粉丝点击