SPOJ GSS4 Can you answer these queries IV (线段树)

题目大意:

给出N个数

0     操作   把 l -----  r之间的数全部开平方

1     操作  输出 l -----r  之间的和

思路分析:

判断区间里的数字是否全相同。如果相同,

将cov 置为该数

查询的时候和更新的时候,如果碰到cov != -1 的  就直接返回就可以了

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#define maxn 200005
#define lson num<<1,s,mid
#define rson num<<1|1,mid+1,e
typedef long long LL;
using namespace std;

LL cov[maxn<<2];

void pushup(int num)
{
    if(cov[num<<1]==cov[num<<1|1])cov[num]=cov[num<<1];
    else cov[num]=-1;
}
void pushdown(int num)
{
    if(cov[num]!=-1)
    {
        cov[num<<1]=cov[num<<1|1]=cov[num];
        cov[num]=-1;
    }
}
void build(int num,int s,int e)
{
    cov[num]=-1;
    if(s==e)
    {
        scanf("%lld",&cov[num]);
        return ;
    }
    int mid=(s+e)>>1;
    build(lson);
    build(rson);
    pushup(num);
}

void update(int num,int s,int e,int l,int r)
{
    if(l<=s && r>=e)
    {
        if(cov[num]!=-1)
        {
            cov[num]=(LL)sqrt(cov[num]*1.0);
            return;
        }
    }
    int mid=(s+e)>>1;
    pushdown(num);
    if(l<=mid)update(lson,l,r);
    if(r>mid)update(rson,l,r);
    pushup(num);
}
LL query(int num,int s,int e,int l,int r)
{
    if(cov[num]!=-1)return cov[num]*(r-l+1);
    if(l<=s && r>=e)
    {
        if(cov[num]!=-1)
        return cov[num]*(e-s+1);
    }
    int mid=(s+e)>>1;
    pushdown(num);
    if(r<=mid)return query(lson,l,r);
    else if(l>mid)return query(rson,l,r);
    else return query(lson,l,mid)+query(rson,mid+1,r);
}
int main()
{
    int CASE=1;
    int n;
    while(scanf("%d",&n)!=EOF)
    {

        build(1,1,n);
        int m;
        scanf("%d",&m);

        printf("Case #%d:\n",CASE++);
        while(m--)
        {
            int op,l,r;
            scanf("%d%d%d",&op,&l,&r);
            if(l>r)swap(l,r);
            if(op)
            {
                printf("%lld\n",query(1,1,n,l,r));
            }
            else update(1,1,n,l,r);
        }

        puts("");
    }
    return 0;
}

SPOJ GSS4 Can you answer these queries IV (线段树)

时间: 2024-10-12 16:35:21

SPOJ GSS4 Can you answer these queries IV (线段树)的相关文章

SP2713 GSS4 - Can you answer these queries IV(线段树)

传送门 解题思路 大概就是一个数很少次数的开方会开到\(1\),而\(1\)开方还是\(1\),所以维护一个和,维护一个开方标记,维护一个区间是否全部为\(1/0\)的标记.然后每次修改时先看是否有全\(1\)或\(0\)的标记,有就不用理了,没有就暴力开方. 代码 #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #define int long long using

SPOJ GSS3 Can you answer these queries III (线段树)

题目大意: 求区间最大子区间的和. 思路分析: 记录左最大,右最大,区间最大. 注意Q_L  和 Q_R  就好. #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #define lson num<<1,s,mid #define rson num<<1|1,mid+1,e #define maxn 55555 using na

SPOJ GSS4 Can you answer these queries IV

Can you answer these queries IV Time Limit: 5000ms Memory Limit: 262144KB This problem will be judged on SPOJ. Original ID: GSS464-bit integer IO format: %lld      Java class name: Main You are given a sequence A of N(N <= 100,000) positive integers.

bzoj 2482: [Spoj GSS2] Can you answer these queries II 线段树

2482: [Spoj1557] Can you answer these queries II Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 145  Solved: 76[Submit][Status][Discuss] Description 给定n个元素的序列. 给出m个询问:求l[i]~r[i]的最大子段和(可选空子段). 这个最大子段和有点特殊:一个数字在一段中出现了两次只算一次. 比如:1,2,3,2,2,2出现了3次,但只算一次,

SPOJ 1557. Can you answer these queries II 线段树

Can you answer these queries II Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 https://www.spoj.com/problems/GSS2/ Description Being a completist and a simplist, kid Yang Zhe cannot solve but get Wrong Answer from most of the OI problems. And he refuse

SPOJ GSS5 Can you answer these queries V ——线段树

[题目分析] GSS1上增加区间左右端点的限制. 直接分类讨论就好了. [代码] #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <map> #include <set> #include <queue> #include <string> #include <iostream> #i

SPOJ GSS3 Can you answer these queries III ——线段树

[题目分析] GSS1的基础上增加修改操作. 同理线段树即可,多写一个函数就好了. [代码] #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <map> #include <set> #include <queue> #include <string> #include <iostream&

Spoj 1716 Can you answer these queries III 线段树 单点修改 区间求最大子段和

题目链接:点击打开链接 == 原来写1的时候已经把更新函数写好了.. #include <cstdio> #include <iostream> #include <algorithm> #include <string.h> #include <math.h> #include <vector> #include <map> using namespace std; #define N 50050 #define Lso

Spoj 2916 Can you answer these queries V 线段树 求任意重叠区间的最大子段和

题目链接:点击打开链接 题意: T个测试数据 n个数字 q个询问 每个询问 : [x1, y1] [x2, y2] 问: int ans = -inf; for(int i = x1; i <= y1; i++) for(int j = max(x2, i); j <= y2; j++) ans = max(ans, query(i, j)); 思路: query_L(int l, int r) 求的是在区间[l,r]内 ,左端点为l的最大子段和. 其他和GSS3差不多. 分类讨论一下给定的区