codevs 4927 线段树练习5

赶在期末考试之前把这道傻逼题调了出来。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 100500
using namespace std;
long long n,m,a[maxn];
long long root,tot=0,ls[maxn<<2],rs[maxn<<2];
long long lazy[maxn<<2],add[maxn<<2],sum[maxn<<2],mi[maxn<<2],mx[maxn<<2];
long long x,y,z;
bool vis[maxn<<2];
void pushup(long long now)
{
    sum[now]=sum[ls[now]]+sum[rs[now]];
    mx[now]=max(mx[ls[now]],mx[rs[now]]);
    mi[now]=min(mi[ls[now]],mi[rs[now]]);
}
void build(long long &now,long long left,long long right)
{
    now=++tot;lazy[now]=0;add[now]=0;
    if (left==right)
    {
        sum[now]=mx[now]=mi[now]=a[left];
        return;
    }
    long long mid=(left+right)>>1;
    build(ls[now],left,mid);
    build(rs[now],mid+1,right);
    pushup(now);
}
void pushdown(long long now,long long left,long long right)
{
    long long mid=(left+right)>>1;
    if (vis[now]==true)
    {
        lazy[ls[now]]=lazy[rs[now]]=mx[ls[now]]=mx[rs[now]]=mi[ls[now]]=mi[rs[now]]=lazy[now];
        sum[ls[now]]=(mid-left+1)*lazy[now];
        sum[rs[now]]=(right-mid)*lazy[now];
        lazy[now]=0;vis[now]=false;vis[ls[now]]=vis[rs[now]]=true;
        add[ls[now]]=0;add[rs[now]]=0;
    }
    if (add[now]!=0)
    {
        add[ls[now]]+=add[now];add[rs[now]]+=add[now];
        sum[ls[now]]+=(mid-left+1)*add[now];
        sum[rs[now]]+=(right-mid)*add[now];
        mx[ls[now]]+=add[now];mx[rs[now]]+=add[now];
        mi[ls[now]]+=add[now];mi[rs[now]]+=add[now];
        add[now]=0;
    }
}
void modify(long long now,long long left,long long right,long long l,long long r,long long p,long long type)
{
    pushdown(now,left,right);
    if ((left==l) && (right==r))
    {
        if (type==1)
        {
            add[now]+=p;sum[now]+=(right-left+1)*p;mx[now]+=p;mi[now]+=p;
            return;
        }
        else
        {
            lazy[now]=p;add[now]=0;sum[now]=p*(right-left+1);
            mx[now]=mi[now]=p;vis[now]=true;
            return;
        }
    }
    long long mid=(left+right)>>1;
    if (r<=mid) modify(ls[now],left,mid,l,r,p,type);
    else if (l>=mid+1) modify(rs[now],mid+1,right,l,r,p,type);
    else
    {
        modify(ls[now],left,mid,l,mid,p,type);
        modify(rs[now],mid+1,right,mid+1,r,p,type);
    }
    pushup(now);
}
long long ask(long long now,long long left,long long right,long long l,long long r,long long type)
{
    pushdown(now,left,right);
    if ((left==l) && (right==r))
    {
        if (type==1) return sum[now];
        else if (type==2) return mx[now];
        else return mi[now];
    }
    long long mid=(left+right)>>1;
    if (r<=mid) return ask(ls[now],left,mid,l,r,type);
    else if (l>=mid+1) return ask(rs[now],mid+1,right,l,r,type);
    else
    {
        if (type==1)
        {
            long long regis1=ask(ls[now],left,mid,l,mid,type);
            long long regis2=ask(rs[now],mid+1,right,mid+1,r,type);
            return regis1+regis2;
        }
        else if (type==2) return max(ask(ls[now],left,mid,l,mid,type),ask(rs[now],mid+1,right,mid+1,r,type));
        else return min(ask(ls[now],left,mid,l,mid,type),ask(rs[now],mid+1,right,mid+1,r,type));
    }
}
int main()
{
    memset(vis,false,sizeof(vis));
    scanf("%lld%lld",&n,&m);
    for (long long i=1;i<=n;i++)
        scanf("%lld",&a[i]);
    build(root,1,n);
    for (long long i=1;i<=m;i++)
    {
        char type[10];
        scanf("%s",type);
        if (type[0]==‘a‘)
        {
            scanf("%lld%lld%lld",&x,&y,&z);
            modify(root,1,n,x,y,z,1);
        }
        else if ((type[0]==‘s‘) && (type[1]==‘e‘))
        {
            scanf("%lld%lld%lld",&x,&y,&z);
            modify(root,1,n,x,y,z,2);
        }
        else if ((type[0]==‘s‘) && (type[1]==‘u‘))
        {
            scanf("%lld%lld",&x,&y);
            printf("%lld\n",ask(root,1,n,x,y,1));
        }
        else if ((type[0]==‘m‘) && (type[1]==‘a‘))
        {
            scanf("%lld%lld",&x,&y);
            printf("%lld\n",ask(root,1,n,x,y,2));
        }
        else
        {
            scanf("%lld%lld",&x,&y);
            printf("%lld\n",ask(root,1,n,x,y,3));
        }
    }
    return 0;
}
时间: 2024-10-16 20:40:57

codevs 4927 线段树练习5的相关文章

[Codevs] 1080 线段树练习

1080 线段树练习 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 一行N个方格,开始每个格子里都有一个整数.现在动态地提出一些问题和修改:提问的形式是求某一个特定的子区间[a,b]中所有元素的和:修改的规则是指定某一个格子x,加上或者减去一个特定的值A.现在要求你能对每个提问作出正确的回答.1≤N<100000,,提问和修改的总数m<10000条. 输入描述 Input Description 输入文件第一行为一个整

【树状数组区间修改区间求和】codevs 1082 线段树练习 3

http://codevs.cn/problem/1082/ [AC] 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=2e5+2; 5 int n; 6 ll a[maxn]; 7 ll c1[maxn]; 8 ll c2[maxn]; 9 int lowbit(int x) 10 { 11 return x&-x; 12 } 13 void add(l

CODEVS 1081 线段树练习 2 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:http://codevs.cn/problem/1081/ 题目描述 Description 给你N个数,有两种操作 1:给区间[a,b]的所有数都增加X 2:询问第i个数是什么? 输入描述 Input Description 第一行一个正整数n,接下来n行n个整数,再接下来一个正整数Q,表示操作的个数. 接下来Q行每行若干个整数.如果第一个数是1,后接3个正整数a,b,X,表示在区间[a,b]内每个数增加X,如果

codevs 1299 线段树 区间更新查询

1299 切水果 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题解 查看运行结果 题目描述 Description 简单的说,一共N个水果排成一排,切M次,每次切[L,R]区间的所有水果(可能有的水果被重复切),每切完一次输出剩下水果数量 数据已重新装配,不会出现OLE错误 时限和数据范围适当修改,避免数据包过大而浪费空间资源 输入描述 Input Description 第1行共包括2个正整数,分别为N,M. 接下来m行每行两个正整数L,R 输出描述 

codevs 4919 线段树练习4

线段树水题.#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 100500 using namespace std; int n,a[maxn],m; int sum[maxn<<2][8],lazy[maxn<<2],tot=0,root,ls[maxn<<2],rs[maxn<<2];

codevs 1080 线段树练习--用树状数组做的

1080 线段树练习 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 一行N个方格,开始每个格子里都有一个整数.现在动态地提出一些问题和修改:提问的形式是求某一个特定的子区间[a,b]中所有元素的和:修改的规则是指定某一个格子x,加上或者减去一个特定的值A.现在要求你能对每个提问作出正确的回答.1≤N<100000,,提问和修改的总数m<10000条. 输入描述 Input Description 输入文件第一行为一个整

[Codevs] 1081 线段树练习 2 ----“分块!”

1081 线段树练习 2 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作 1:给区间[a,b]的所有数都增加X 2:询问第i个数是什么? 输入描述 Input Description 第一行一个正整数n,接下来n行n个整数,再接下来一个正整数Q,表示操作的个数. 接下来Q行每行若干个整数.如果第一个数是1,后接3个正整数a,b,X,表示在区间[a,b]内每个数增加X,如果是2,后面跟1个整数i, 表示

codevs 1082 线段树练习3

1082 线段树练习 3 时间限制: 3 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区间[a,b]的所有数增加X 2:询问区间[a,b]的数的和. 输入描述 Input Description 第一行一个正整数n,接下来n行n个整数, 再接下来一个正整数Q,每行表示操作的个数, 如果第一个数是1,后接3个正整数, 表示在区间[a,b]内每个数增加X,如果是2, 表示操作2询问区间[a,b]的和是多少.

codevs 1082 线段树联系3

1082 线段树练习 3 时间限制: 3 s 空间限制: 128000 KB 题目等级 : 大师 Master 题解 题目描述 Description 给你N个数,有两种操作: 1:给区间[a,b]的所有数增加X 2:询问区间[a,b]的数的和. 输入描述 Input Description 第一行一个正整数n,接下来n行n个整数, 再接下来一个正整数Q,每行表示操作的个数, 如果第一个数是1,后接3个正整数, 表示在区间[a,b]内每个数增加X,如果是2, 表示操作2询问区间[a,b]的和是多