这个是我做的线段树第三个题,比前两个区间求和稍微麻烦了一些!

大致意思是:

给一组棍子染色,不同的颜色有不同的值,执行一系列的区间染色后,问这组棍子的总值是多少。

这题我用了两种方法,说是两种,其实就中间的某些细节不太一样!

Nuumber one:

每个线段树的结点,存储该结点所代表区间的染色状况num,如果该区间全为同样的颜色,则用一个正数(1,2,3)表示,如果含有多种颜色,则用-1表示,每次执行染色操作时,如果所要染的颜色与区间颜色一样,则停止,如果所要染区间跟当前结点区间一致,则直接将所要染颜色赋给当前结点的num,否则,如果当前结点区间不是混合色,则先将当前结点的颜色赋给左右子结点的num,并递归下去。

# include<stdio.h>
# define N 400000
struct node{
    int left,right,mid;
    int num;
}a[N];
int val;
void make(int s,int t,int step)
{
    a[step].num=1;
    a[step].left=s;
    a[step].right=t;
    a[step].mid=(s+t)/2;
    if(s==t) return;
    make(s,a[step].mid,2*step);
    make(a[step].mid+1,t,2*step+1);

}
void change(int ans1,int ans2,int step)
{
    if(a[step].num==val) return; 
    if(a[step].left==ans1 && a[step].right==ans2 )  
    {a[step].num=val;return;}
    if(a[step].num!=-1) {a[step*2].num=a[step*2+1].num=a[step].num;}
    a[step].num=-1;
    if(ans1>a[step].mid) change(ans1,ans2,2*step+1);
    else if(ans2<=a[step].mid) change(ans1,ans2,2*step);
    else 
    {
        change(ans1,a[step].mid,2*step);
        change(a[step].mid+1,ans2,2*step+1);
    }
}
int count(int step)
{
    if(a[step].num>0) return (a[step].right-a[step].left+1)*a[step].num;
    return count(step*2)+count(2*step+1);
}
int main()
{
    int ncase=0,n,m,t,ans1,ans2;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        make(1,n,1);
        while(m--)
        {
            scanf("%d%d%d",&ans1,&ans2,&val);
            change(ans1,ans2,1);
        }
        printf("Case %d: The total value of the hook is %d.\n",++ncase,count(1));
    }
    return 0;
}
Number two:
成段更新,总区间求和!
# include<stdio.h>
# define N 400000
struct node{
    int left,right,mid;
    int num,value;
}a[N];
int val;
void make(int s,int t,int step)
{
    a[step].left=s;
    a[step].right=t;
    a[step].mid=(s+t)/2;
    a[step].num=t-s+1;
    a[step].value=1;
    if(s==t) return;
    make(s,a[step].mid,2*step);
    make(a[step].mid+1,t,2*step+1);
}
void change(int ans1,int ans2,int step)
{
    if(a[step].value==val) return; 
    if(ans1==a[step].left && a[step].right==ans2)  
    {
        a[step].value=val;
        a[step].num=(a[step].right-a[step].left+1)*a[step].value;
        return;
    }
    if(a[step].value>0) 
    {
        a[step*2].value=a[step].value;
        a[step*2].num=(a[step*2].right-a[step*2].left+1)*a[step*2].value;
        
        a[step*2+1].value=a[step].value;
        a[step*2+1].num=(a[step*2+1].right-a[step*2+1].left+1)*a[step*2+1].value;
        a[step].value=0;
    }
    if(ans1>a[step].mid) change(ans1,ans2,2*step+1);
    else if(ans2<=a[step].mid) change(ans1,ans2,2*step);
    else 
    {
        change(ans1,a[step].mid,2*step);
        change(a[step].mid+1,ans2,2*step+1);
    }
    a[step].num=a[2*step].num+a[2*step+1].num;
}
int main()
{
    int ncase=0,n,m,t,ans1,ans2;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        make(1,n,1);
        while(m--)
        {
            scanf("%d%d%d",&ans1,&ans2,&val);
            change(ans1,ans2,1);
        }
        printf("Case %d: The total value of the hook is %d.\n",++ncase,a[1].num);
    }
    return 0;
}





posted on 2010-08-21 21:23  奋斗青春  阅读(1493)  评论(2编辑  收藏  举报