poj -3468 + HDU - 1698 线段树区间修改,区间查询

https://cn.vjudge.net/problem/POJ-3468          https://cn.vjudge.net/problem/HDU-1698

两者只有一个地方是不太一样的,就是他们需要处理的方式

POJ的是给你一个区间,让你加减一个数,从而改变区间的值,HDU是让你修改区间的值,而不是进行累加和累减的操作

先上POJ的

#include <iostream>
#include <cstdio>
#include <string>
using namespace std;
typedef long long ll;
const int MAX = 100005;
const int mod = 1e9 + 7;
ll c[MAX<<2];
ll lay[MAX<<2];
void push_down(int id,int l,int r,int mid)//这个函数里面同样是+ ;
{
    if(lay[id])
    {
        c[id<<1]+=(ll)(mid-l+1)*lay[id];
        c[id<<1|1]+=(ll)(r-mid)*lay[id];
        lay[id<<1]+=lay[id];
        lay[id<<1|1]+=lay[id];
        lay[id]=0;
    }
}
void push_up(int x)
{
    c[x]=c[x<<1]+c[x<<1|1];
}
void build(int id,int l,int r)
{
    if(l==r)
    { cin>>c[id];
       // scanf("%d",&c[id]);
        return;
    }
    int m=(l+r)>>1;
    build(id<<1,l,m);
    build(id<<1|1,m+1,r);
    push_up(id);
}
void updata(int id,int l,int r,int L,int R,int V)
{
    if(L<=l&&R>=r)
    {
        c[id]+=(ll)(r-l+1)*V;//这个地方是加上原来的区间数,因为你更改的数是要加上的
        lay[id]+=(ll)V;return;//lay数组是说在id这个点需要加减的数,因此也是要+
    }
    int m=(l+r)>>1;
    push_down(id,l,r,m);
    if(L<=m)
        updata(id<<1,l,m,L,R,V);
    if(R>m) updata(id<<1|1,m+1,r,L,R,V);
    push_up(id);
}
ll sum(int id,int l,int r,int L,int R)
{
    if(L<=l&&R>=r)
        return c[id];
    int m=(l+r)>>1;ll ans=0;
    push_down(id,l,r,m);
    if(L<=m)
        ans+=sum(id<<1,l,m,L,R);
    if(R>m) ans+=sum(id<<1|1,m+1,r,L,R);
    return ans;
}
int main()
{
    int n;int Q;
    ios::sync_with_stdio(0);cin.tie(0);
    //scanf("%d %d%*c",&n,&Q);
    cin>>n>>Q;
    int m=n;
    build(1,1,n);
    while(Q--)
    {
        char s;int x,y,v;
        //scanf("%c%*c",&s);
        cin>>s;
        if(s=='Q'){
            //scanf("%d %d",&x,&y);
                cin>>x>>y;
            //printf("%d\n",sum(1,1,n,x,y));
            cout<<sum(1,1,n,x,y)<<endl;
        }
        else if(s=='C'){
            //scanf("%d %d %d",&x,&y,&v);
            cin>>x>>y>>v;
            updata(1,1,n,x,y,v);
        }
    }
    return 0;
}

需要注意的是这道题需要Longlong的范围,否则WA

下面是HDU的

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MOD=1<<17;
ll n;
int lay[MOD<<1];//表示当前点的标记
int c[MOD<<1];//表示第i个点的值,因为线段树是从上往下建的,所以最低端的数才是最初的数据
void push_up(int x)
{
    c[x]=c[x<<1]+c[x<<1|1];
}
void push_down(int id,int l,int r,int m)
{
    if(lay[id])
    {
        c[id<<1]=(m-l+1)*lay[id];
        c[id<<1|1]=(r-m)*lay[id];
        lay[id<<1]=lay[id];
        lay[id<<1|1]=lay[id];
        lay[id]=0;
    }
}
void build(int id,int l,int r)
{
    if(l==r)
    {
        c[id]=1;
        return ;
    }
    int m=(l+r)>>1;
        build(id<<1,l,m);
        build(id<<1|1,m+1,r);
    push_up(id);
}
void update(int id,int l,int r,int now_l,int now_r,int val)
{
    if(now_l<=l&&now_r>=r)
    {
        c[id]=(r-l+1)*val;//这里就是直接赋值,包括上面的push_down函数同样是赋值操作
        if(l^r)//这一步就是判断是否找到最底部这样就不用再进行操作,去掉if语句也行
            lay[id]=val;
        return;
    }
    int m=(l+r)>>1;
    push_down(id,l,r,m);
    if(now_l<=m) update(id<<1,l,m,now_l,now_r,val);
     if(now_r>m) update(id<<1|1,m+1,r,now_l,now_r,val);
    push_up(id);
}
int  sum(int id,int l,int r,int now_l,int now_r)
{
    if(now_l<=l&&now_r>=r)
    {
        return c[id];
    }
    int m=(l+r)>>1;
    int ans=0;
    push_down(id,l,r,m);
    if(now_l<=m) ans+=sum(id<<1,l,m,now_l,now_r);
     if(now_r>=1+m) ans+=sum(id<<1|1,m+1,r,now_l,now_r);
    return ans;
}
int main()
{
    int t;
    ios::sync_with_stdio(0);cin.tie(0);
    cin>>t;
    int q,x,y,z,n;
         int s=1;
    while(t--)
    {
        memset(lay,0,sizeof lay);
        memset(c,0,sizeof c);
        cin>>n>>q;
        build(1,1,n);
        //update(1,1,n,1,n,1);
        while(q--)
        {
            cin>>x>>y>>z;
            update(1,1,n,x,y,z);
        }
        cout<<"Case "<<s++<<": The total value of the hook is "<<sum(1,1,n,1,n)<<"."<<endl;
    }
}

 其实HDU这道题只用update这个函数就可以,开始建树用update(1,1,n,1,n,1),输出c[1]就可以

猜你喜欢

转载自blog.csdn.net/c___c18/article/details/81700528