hdu 1698

这个题是线段树区间更新,区间查询

一个语句顺序错了,我弄了2个小时才找到(细心才是王道)

#include<stdio.h>
#include<string.h>
#include<string>
#include<algorithm>
#include<iostream>
#define maxn 100005
using namespace std;
struct Node
{
    int left,right;
    int val,lazy;
    //val是值,lazy是延迟标记
} tree[maxn<<2];
int A[maxn];

void build(int L,int R,int rt)//创建
{
    tree[rt].left=L;
    tree[rt].right=R;
    tree[rt].lazy=0;//就是这,浪费了我2个小时
    if(L==R)
    {
        tree[rt].val=A[L];
        return ;
    }
    int m=(L+R)>>1;
    build(L,m,rt<<1);
    build(m+1,R,rt<<1|1);
    tree[rt].val=tree[rt<<1].val+tree[rt<<1|1].val;
}
void updata(int rt,int i,int val)//单点更新
{
    if(tree[rt].left==tree[rt].right)
    {
        tree[rt].val=val;
        return ;
    }
    int m=(tree[rt].right+tree[rt].left)>>1;
    if(i<=m) updata(rt<<1,i,val);
    else updata(rt<<1|1,i,val);
    tree[rt].val=tree[rt<<1].val+tree[rt<<1|1].val;
}
void pushdown(int rt)//根据延迟标记向下更新
{
    if(tree[rt].lazy>0)
    {
        tree[rt<<1].lazy=tree[rt].lazy;
        tree[rt<<1|1].lazy=tree[rt].lazy;
        tree[rt<<1].val=tree[rt].lazy*(tree[rt<<1].right-tree[rt<<1].left+1);
        tree[rt<<1|1].val=tree[rt].lazy*(tree[rt<<1|1].right-tree[rt<<1|1].left+1);
        tree[rt].lazy=0;
    }

}
void  updata2(int l,int r,int rt,int val)//区间更新
{
    if(r<tree[rt].left||l>tree[rt].right)return ;
    if(l<=tree[rt].left&&r>=tree[rt].right)
    {
        tree[rt].lazy=val;//加上延迟标记
        tree[rt].val=val*(tree[rt].right-tree[rt].left+1);//更新这个区间的值
        return ;
    }
    pushdown(rt);
    int mid=(tree[rt].left+tree[rt].right)>>1;
    if(l<=mid) updata2(l,r,rt<<1,val);
    if(r>mid)updata2(l,r,rt<<1|1,val);
    tree[rt].val=tree[rt<<1].val+tree[rt<<1|1].val;
}
//根据以上pushdown函数和updata2函数可以看出,具有lazy标记不为0的节点,这个节点的值已经是更新过的,只需要将更新标记下移并且一次只更新左儿子和右儿子的值
//孙子节点的值下一次再更新
query(int l,int r,int rt)
{

    if(l<=tree[rt].left&&r>=tree[rt].right)
    {
        return tree[rt].val;
    }
    int sum=0;
    pushdown(rt);
    int m=(tree[rt].left+tree[rt].right)>>1;
    if(l>m)sum+=query(l,r,rt<<1|1);
    else if(r<=m)sum+=query(l,r,rt<<1);
    else
    {
        sum+=query(l,r,rt<<1);
        sum+=query(l,r,rt<<1|1);
    }
    return sum;
}

int main()
{
    int i,j,n,k,t;
    int cas=1;
    int m;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        int a,b,c;
        int tmp;
        for(i=1; i<=n; ++i)
        {
            A[i]=1;
        }
        build(1,n,1);
        for(i=0; i<m; ++i)
        {
            scanf("%d%d%d",&a,&b,&c);
            updata2(a,b,1,c);
        }
        printf("Case %d: The total value of the hook is %d.\n",cas++,query(1,n,1));
    }



    return 0;
}
/*
1
10
2
1 5 2
5 9 3

*/




我参考的代码段:

/*
 线段树+修改区间+询问区间
 */
 #include<stdio.h>
 #include<string.h>
 #include<stdlib.h>
 #include<algorithm>
 #include<iostream>
 #include<queue>
 #include<vector>
 #include<map>
 #include<math.h>
 typedef long long ll;
 //typedef __int64 int64;
 const int maxn = 100005;
 const int maxm = 1005;
 const int inf = 0x7FFFFFFF;
 const double pi = acos(-1.0);
 const double eps = 1e-8;
 using namespace std;
 #define LEFT( x ) (x<<1)
 #define RIGHT( x ) ((x<<1)+1)
 struct node{
     int l,r,sum;
     int flag;
 }tree[ maxn<<2 ];
 int data[ maxn ];
 void pushup( int n ){
     tree[ n ].sum = tree[ LEFT( n ) ].sum+tree[ RIGHT( n ) ].sum;
     return ;
 }
 void pushdown( int n,int m ){//下标为n,这段区间有m个数
     if( tree[ n ].flag!=0 ){
         tree[ LEFT( n ) ].flag = tree[ RIGHT( n ) ].flag = tree[ n ].flag;
         tree[ LEFT( n ) ].sum =  tree[ n ].flag*(m-m/2);//tree[ n ].flag*((m+1)/2);
         tree[ RIGHT( n ) ].sum = tree[ n ].flag*(m/2);//tree[ n ].flag*( m-(m+1)/2 );
         tree[ n ].flag = 0;
     }
     return;
 }
 void build( int l,int r,int n ){
     if( l==r ){
         tree[ n ].sum = data[ l ];
         tree[ n ].flag = 0;
         tree[ n ].l=tree[ n ].r = l;
         return ;
     }
     tree[ n ].flag = 0;
     tree[ n ].l = l;
     tree[ n ].r = r;
     int mid;
     mid = (l+r)>>1;
     build( l,mid,LEFT( n ) );
     build( mid+1,r,RIGHT( n ) );
     pushup( n );
     return;
 }
 void update( int a,int b,int c,int l,int r,int n ){
     if( a==l&&b==r ){
         tree[ n ].flag = c;
         tree[ n ].sum = (r-l+1)*c;
         return ;
     }
     pushdown( n,r-l+1 );
     //printf("test\n");
     int mid;
     mid = (l+r)>>1;
     if( mid>=b ) update( a,b,c,l,mid,LEFT( n ) );
     else if( mid<a ) update( a,b,c,mid+1,r,RIGHT( n ));
     else {
         update( a,mid,c,l,mid,LEFT( n ) );
         update( mid+1,b,c,mid+1,r,RIGHT( n ) );
     }
     pushup( n );
     return ;
 }
 int query( int a,int b,int l,int r,int n ){
     if( a==l&&b==r ){
         return tree[ n ].sum;
     }
     pushdown( n,r-l+1 );
     int mid;
     mid = (l+r)>>1;
     if( mid>=b ) return query( a,b,l,mid,LEFT( n ) );
     else if( mid<a ) return query( a,b,mid+1,r,RIGHT( n ));
     else return query( a,mid,l,mid,LEFT( n ) )+query( mid+1,b,mid+1,r,RIGHT( n ));
 }
 int main(){
     int ca;
     scanf("%d",&ca);
     for( int t=1;t<=ca;t++ ){
         int n;
         scanf("%d",&n);
         for( int i=1;i<=n;i++ ){
             data[ i ] = 1;
         }
         build( 1,n,1 );
         int op;
         scanf("%d",&op);
         while( op-- ){
             int a,b,c;
             scanf("%d%d%d",&a,&b,&c);
             update( a,b,c,1,n,1 );
         }
         printf("Case %d: The total value of the hook is %d.\n",t,tree[ 1 ].sum);
     }
     return 0;
 }

贴上线段树延迟标记写法:


void pushup(int index){  
    tree[index].sum = tree[index<<1].sum+tree[index<<1|1].sum;  
    tree[index].mx = max(tree[index<<1].mx,tree[index<<1|1].mx);  
    tree[index].mn = min(tree[index<<1].mn,tree[index<<1|1].mn);  
}  
void pushdown(int index){  
    //说明该区间之前更新过  
    //要想更新该区间下面的子区间,就要把上次更新该区间的值向下更新  
    if(tree[index].add > 0){  
        //替换原来的值  
        /* 
        tree[index<<1].sum = (tree[index<<1].r-tree[index<<1].l+1)*tree[index].add; 
        tree[index<<1|1].sum = (tree[index<<1|1].r-tree[index<<1|1].l+1)*tree[index].add; 
        tree[index<<1].mx = tree[index].add; 
        tree[index<<1|1].mx = tree[index].add; 
        tree[index<<1].mn = tree[index].add; 
        tree[index<<1|1].mn = tree[index].add; 
        tree[index<<1].add = tree[index].add; 
        tree[index<<1|1].add = tree[index].add; 
        tree[index].add = 0;*/  
        //在原来的值的基础上加上val  
          
        tree[index<<1].sum += (tree[index<<1].r-tree[index<<1].l+1)*tree[index].add;  
        tree[index<<1|1].sum +=(tree[index<<1|1].r-tree[index<<1|1].l+1)*tree[index].add;  
        tree[index<<1].mx += tree[index].add;  
        tree[index<<1|1].mx += tree[index].add;  
        tree[index<<1].mn += tree[index].add;  
        tree[index<<1|1].mn += tree[index].add;  
        tree[index<<1].add += tree[index].add;  
        tree[index<<1|1].add += tree[index].add;  
        tree[index].add = 0;  
  
    }  
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值