线段树(区间修改,区间查询)

/*
 * 线段树模板
 * 区间修改 区间查询
 * 版本一:当前区间值正确,tag未下传
 */
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
const int MAXN=1e5+5;
const LL INF=2e18;
//const int INF=0x3f3f3f3f;//根据是否超long long修改
LL a[MAXN];

//线段树节点结构体
struct Node{
    int left,right;//左右边界
    LL mi,ma;//最小值 最大值
    LL sum;//和
    LL add;//增减标记
    int set;//重置标记
}tree[MAXN*4];//空间开四倍

//向上更新
void PushUp(int rt){
    int lson=rt<<1,rson=rt<<1|1;
    tree[rt].mi=min(tree[lson].mi,tree[rson].mi);
    tree[rt].ma=max(tree[lson].ma,tree[rson].ma);
    tree[rt].sum=tree[lson].sum+tree[rson].sum;
}

//向下传递标记
void PushDown(int rt){
    if(tree[rt].left<tree[rt].right){//如果不是叶子
        int lson=rt<<1,rson=rt<<1|1;
        if(tree[rt].set!=-1){//set初始为一个不会重置到的数,这里是-1
            tree[lson].set=tree[rt].set;tree[rson].set=tree[rt].set;
            tree[lson].add=tree[rson].add=0;//add失效
            tree[lson].mi=tree[rson].mi=tree[rt].set;
            tree[lson].ma=tree[rson].ma=tree[rt].set;
            tree[lson].sum=(LL)tree[rt].set*(tree[lson].right-tree[lson].left+1);
            tree[rson].sum=(LL)tree[rt].set*(tree[rson].right-tree[rson].left+1);
            tree[rt].set=-1;
        }
        if(tree[rt].add){
            tree[lson].add+=tree[rt].add;tree[rson].add+=tree[rt].add;
            tree[lson].mi+=tree[rt].add;tree[rson].mi+=tree[rt].add;
            tree[lson].ma+=tree[rt].add;tree[rson].ma+=tree[rt].add;
            tree[lson].sum+=(LL)tree[rt].add*(tree[lson].right-tree[lson].left+1);
            tree[rson].sum+=(LL)tree[rt].add*(tree[rson].right-tree[rson].left+1);
            tree[rt].add=0;
        }
    }
}

//建立函数
void Build(int rt,int L,int R){
    tree[rt].left=L;tree[rt].right=R;tree[rt].add=0;tree[rt].set=-1;
    if(L==R) {tree[rt].sum=tree[rt].mi=tree[rt].ma=a[L]; return;}
    int mid=(tree[rt].left+tree[rt].right)>>1;
    Build(rt<<1,L,mid);//只有Build时LR才会变
    Build(rt<<1|1,mid+1,R);
    PushUp(rt);
}

LL QuerySum(int rt,int L,int R){
    if(R<tree[rt].left||L>tree[rt].right) return  0;
    if(L<=tree[rt].left&&tree[rt].right<=R)  return tree[rt].sum;
    PushDown(rt);
    int mid=(tree[rt].left+tree[rt].right)>>1;
    LL res=0;
    if(L<=mid)  res+=QuerySum(rt<<1,L,R);
    if(R>mid)   res+=QuerySum(rt<<1|1,L,R);
    PushUp(rt);
    return  res;
}

LL QueryMin(int rt,int L,int R){
    if(L<=tree[rt].left&&tree[rt].right<=R) return tree[rt].mi;
    PushDown(rt);
    int mid=(tree[rt].left+tree[rt].right)>>1;
    LL res=INF;
    if(L<=mid) res=min(res,QueryMin(rt<<1,L,R));
    if(R>mid) res=min(res,QueryMin(rt<<1|1,L,R));
    PushUp(rt);
    return  res;
}

LL QueryMax(int rt,int L,int R){
    if(L<=tree[rt].left&&tree[rt].right<=R) return  tree[rt].ma;//完全包含才产生贡献
    PushDown(rt);
    int mid=(tree[rt].left+tree[rt].right)>>1;
    LL res=-INF;
    if(L<=mid) res=max(res,QueryMax(rt<<1,L,R));
    if(R>mid) res=max(res,QueryMax(rt<<1|1,L,R));
    PushUp(rt);
    return  res;
}

void UpdateAdd(int rt,int L,int R,int x){//把区间[L,R]加上x
    if(L<=tree[rt].left&&tree[rt].right<=R){
        tree[rt].add+=x;
        tree[rt].sum+=(LL)x*(tree[rt].right-tree[rt].left+1);
        tree[rt].mi+=x;tree[rt].ma+=x;
        return;
    }
    PushDown(rt);
    int mid=(tree[rt].left+tree[rt].right)>>1;
    if(L<=mid) UpdateAdd(rt<<1,L,R,x);
    if(R>mid) UpdateAdd(rt<<1|1,L,R,x);
    PushUp(rt);
}

void Display(int rt){
    cout<<"-------------"<<endl;
    cout<<"id: "<<rt<<endl;
    cout<<"["<<tree[rt].left<<","<<tree[rt].right<<"]"<<endl;
    cout<<"mi: "<<tree[rt].mi<<endl;
    cout<<"ma: "<<tree[rt].ma<<endl;
    cout<<"sum: "<<tree[rt].sum<<endl;
    cout<<"add: "<<tree[rt].add<<endl;
    cout<<"set: "<<tree[rt].set<<endl;
}

void bfs(int rt){
    queue<int> q;
    while(!q.empty()) q.pop();
    q.push(rt);
    while(!q.empty()){
        int fst=q.front();
        q.pop();
        Display(fst);
        if(tree[fst].right>tree[fst].left){
            q.push(fst<<1);
            q.push(fst<<1|1);
        }
    }
}

void UpdateSet(int rt,int L,int R,int x){//把区间[x,y]置为x
    if(L<=tree[rt].left&&tree[rt].right<=R){
        tree[rt].set=x;
        tree[rt].sum=(LL)x*(tree[rt].right-tree[rt].left+1);
        tree[rt].mi=x;tree[rt].ma=x;
        tree[rt].add=0;
        return;
    }
    PushDown(rt);
    int mid=(tree[rt].left+tree[rt].right)>>1;
    if(L<=mid) UpdateSet(rt<<1,L,R,x);
    if(R>mid){
        UpdateSet(rt<<1|1,L,R,x);
    }
    PushUp(rt);
}

int main(){
    int n,m;//n个数 m次询问
    while(scanf("%d%d",&n,&m)!=EOF){
        for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
        Build(1,1,n);//建立线段树
        int op,x,y,z;
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&op,&x,&y);
            if(op==1){//询问[x,y]的和
                printf("Case #%d:\n",i);
                printf("%lld\n",QuerySum(1,x,y));
            }else if(op==2){//询问[x,y]的最大值
                printf("Case #%d:\n",i);
                printf("%lld\n",QueryMax(1,x,y));
            }else if(op==3){//询问[x,y]的最小值
                printf("Case #%d:\n",i);
                printf("%lld\n",QueryMin(1,x,y));
            }else if(op==4){//在[x,y]区间加上z
                scanf("%d",&z);
                UpdateAdd(1,x,y,z);
            }else{//把[x,y]置为z
                scanf("%d",&z);
                UpdateSet(1,x,y,z);
            }
        }
    }
    return 0;
}
/*
6 20
1 2 3 4 5 6
3
1 6
4
1 6 1
3
1 6
5
2 4 8
3
1 6
*/

/*
2 8 8 8 6 7
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define lson (rt<<1)
#define rson (rt<<1|1)
#define lowbit(x) ((x)&(-(x)))
using namespace std;
typedef long long LL;
const int MAXN=2e5+5;
int val[MAXN];

struct node
{
    int tot;
    int left,right;
    int mark;
}tree[MAXN*4];

int build(int rt,int left,int right)
{
    tree[rt].mark=0;
    tree[rt].left=left;
    tree[rt].right=right;
    if(left==right) return tree[rt].tot=val[left];
    int mid=(left+right)/2;
    int a=build(lson,left,mid);
    int b=build(rson,mid+1,right);
    return tree[rt].tot=a+b;
}

void update_mark(int rt)
{
    if(tree[rt].mark)
    {
        tree[rt].tot=tree[rt].mark*(tree[rt].right-tree[rt].left+1);
        if(tree[rt].left!=tree[rt].right)
            tree[lson].mark=tree[rson].mark=tree[rt].mark;
        tree[rt].mark=0;
    }
}

int calc(int rt,int left,int right)
{
    update_mark(rt);
    if(tree[rt].left>right||tree[rt].right<left) return 0;
    if(left<=tree[rt].left&&tree[rt].right<=right) return tree[rt].tot;
    int a=calc(lson,left,right);
    int b=calc(rson,left,right);
    return a+b;
}

int update(int rt,int left,int right,int val)
{
    update_mark(rt);
    if(tree[rt].left>right||tree[rt].right<left) return tree[rt].tot;
    if(tree[rt].left>=left&&tree[rt].right<=right)
    {
        tree[rt].mark=val;
        return tree[rt].tot=val*(tree[rt].right-tree[rt].left+1);
    }
    int a=update(lson,left,right,val);
    int b=update(rson,left,right,val);
    return tree[rt].tot=a+b;
}

int main()
{
    int T;
    scanf("%d",&T);
    int cas=0;
    while(T--)
    {
        int n,q;
        scanf("%d%d",&n,&q);
        for(int i=1;i<=n;++i)
        {
            val[i]=1;
        }
        build(1,1,n);
        int x,y,z;
        for(int i=1;i<=q;++i)
        {
            scanf("%d%d%d",&x,&y,&z);
            update(1,x,y,z);
        }
        printf("Case %d: The total value of the hook is %d.\n",++cas,calc(1,1,n));
    }
    return 0;
}
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define lson (rt<<1)
#define rson (rt<<1|1)
#define lowbit(x) ((x)&(-(x)))
using namespace std;
typedef long long LL;
const int MAXN=1e5+5;
int val[MAXN];

struct node
{
    LL tot,add;
    int left,right;
}tree[MAXN*4];

void pushup(int rt)
{
    tree[rt].tot=tree[lson].tot+tree[rson].tot;
}

void pushdown(int rt,int m)
{
    if(tree[rt].add)
    {
        tree[lson].add+=tree[rt].add;
        tree[rson].add+=tree[rt].add;
        tree[lson].tot+=(m-(m>>1))*tree[rt].add;
        tree[rson].tot+=(m>>1)*tree[rt].add;
        tree[rt].add=0;
    }
}

void build(int rt,int left,int right)
{
    tree[rt].add=0;
    tree[rt].left=left;
    tree[rt].right=right;
    if(left==right) {tree[rt].tot=val[left];return;}
    int mid=(left+right)>>1;
    build(lson,left,mid);
    build(rson,mid+1,right);
    pushup(rt);
}

LL query(int rt,int left,int right)
{
    if(left<=tree[rt].left&&tree[rt].right<=right) return tree[rt].tot;
    pushdown(rt,tree[rt].right-tree[rt].left+1);
    int mid=(tree[rt].left+tree[rt].right)>>1;
    LL res=0;
    if(left<=mid) res+=query(lson,left,right);
    if(right>mid) res+=query(rson,left,right);
    return res;
}

void update(int rt,int left,int right,int val)
{
    if(left<=tree[rt].left&&tree[rt].right<=right)
    {
        tree[rt].add+=val;
        tree[rt].tot+=(LL)val*(tree[rt].right-tree[rt].left+1);
        return;
    }
    pushdown(rt,tree[rt].right-tree[rt].left+1);
    int mid=(tree[rt].left+tree[rt].right)>>1;
    if(left<=mid) update(lson,left,right,val);
    if(right>mid) update(rson,left,right,val);
    pushup(rt);
}

int main()
{
    int n,q;
    while(scanf("%d%d",&n,&q)!=EOF)
    {
        for(int i=1;i<=n;++i)
        {
            scanf("%d",&val[i]);
        }
        build(1,1,n);
        char op;
        int x,y,z;
        for(int i=1;i<=q;++i)
        {
            getchar();
            scanf("%c",&op);
            //cout<<"log: "<<op<<endl;
            if(op=='Q')
            {
                scanf("%d%d",&x,&y);
                printf("%lld\n",query(1,x,y));
            }else
            {
                scanf("%d%d%d",&x,&y,&z);
                update(1,x,y,z);
            }
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值