【SP2713 GSS4 - Can you answer these queries IV】 题解

题目链接:https://www.luogu.org/problemnew/show/SP2713

真暴力啊。

开方你开就是了,开上6次就都没了。

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
using namespace std;
const int maxn = 100100;
inline ll read(){
    ll k = 0 ; char c = getchar() ;
    while (!isdigit(c)) c = getchar() ;
    while (isdigit(c)) k = k * 10 + c - 48, c = getchar() ;
    return k  ;
}
ll n, m, a[maxn], t=0;
class Segment_Tree{
    #define lson l, mid, rt<<1
    #define rson mid+1, r, rt<<1|1
    public:
        ll tree[maxn<<2];
        void build(ll l, ll r, ll rt)
        {
            if(l == r)
            {
                tree[rt] = a[l];
                return;
            }
            ll mid = (l + r) >> 1;
            build(lson);
            build(rson);
            PushUP(rt);
        }

        void update(ll left, ll right, ll l, ll r, ll rt)
        {
            if(left <= l && r <= right)
            {
                if(tree[rt] <= r - l + 1) return;
                else
                {
                    if(l == r)
                    {
                        tree[rt] = (ll)sqrt((double)tree[rt]);
                        return;
                    }
                }
            }
            ll mid = (l + r) >> 1;
            PushUP(rt);
            if(left <= mid) update(left, right, lson);
            PushUP(rt);
            if(right > mid) update(left, right, rson);
            PushUP(rt);
        }

        ll query(ll left, ll right, ll l, ll r, ll rt)
        {
            ll res = 0;
            if(left <= l && right >= r)
            {
                return tree[rt];
            }
            ll mid = (l + r) >> 1;
            if(left <= mid) res += query(left, right, lson);
            if(right > mid) res += query(left, right, rson);
            return res;
        }

    private:
        void PushUP(ll rt)
        {
            tree[rt] = tree[rt<<1] + tree[rt<<1|1];
        }
}T;
int main()
{
    while(~scanf("%lld",&n))
    {
        t++;
        printf("Case #%d:\n",t);
        memset(a, 0, sizeof(a));
        for(ll i = 1; i <= n; i++)
        a[i] = read();
        T.build(1,n,1);
        m = read();
        for(ll i = 1; i <= m; i++)
        {
            ll opt, x, y;
            opt = read();
            x = read();
            y = read();
            if(y < x) swap(x, y);
            if(opt == 0)
            T.update(x,y,1,n,1);
            else
            printf("%lld\n",T.query(x,y,1,n,1));
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/MisakaAzusa/p/9803084.html

时间: 2024-08-30 09:36:17

【SP2713 GSS4 - Can you answer these queries IV】 题解的相关文章

SP2713 GSS4 - Can you answer these queries IV

传送门 \(ZHX\; TQL\) Orz 这道题目我们可以用线段树维护-- 可能有\(dalao\)会问:"线段树怎么维护区间开平方?" 而这道题的精髓就在于,它要我们维护的操作是开平方+下取整.也就是说经过一定的次数,要开平方的数会慢慢缩小为"\(1\)",这个次数是很小的,而\(\sqrt 1=1\). 所以在修改时,我们可以先查询这个区间是否全是"1",如果是,那我们就不管它,再去寻找其他的区间进行修改,如果这个区间里有其他数,我们就将这

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 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> #incl

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.

「SP2713」GSS4 - Can you answer these queries IV

传送门 Luogu 解题思路 区间开方以及区间求和. 考虑用线段树来做. 开方操作看似没有任何结合律可言,但这题有另外一个性质: 一个数的初始值不超过 \(10^{18}\) ,而这个数被开方6次左右就可以到1或0,并且1和0都是不需要再开方的. 所以我们记一下每个节点代表区间的最大值,若该值小于等于1,那么就不需要再进入下一层递归,否则就向下递归修改,修改次数最坏也不过是 \(O(6n)\) 左右,线段树完全没压力,于是这题就做完了. 细节注意事项 咕咕咕 参考代码 #include <alg

题解 SP2713 【GSS4 - Can you answer these queries IV】

用计算器算一算,就可以发现\(10^{18}\)的数,被开方\(6\)次后就变为了\(1\). 所以我们可以直接暴力的进行区间修改,若这个数已经到达\(1\),则以后就不再修改(因为\(1\)开方后还是\(1\)),用并查集和树状数组进行维护. 这个方法用了P2391 白雪皑皑的思想处理,用并查集标记该点已经不再用替换. 和我这题CF920F[SUM和REPLACE]的方法相同. \(code\): #include<bits/stdc++.h> #define maxn 500010 #de

Spoj 2713 Can you answer these queries IV 水线段树

题目链接:点击打开链接 题意: 给定n长的序列 下面2个操作 0 x y 给[x,y]区间每个数都 sqrt 1 x y 问[x, y] 区间和 #include <stdio.h> #include <iostream> #include <algorithm> #include <string.h> #include <queue> #include <math.h> #include <vector> #includ

SP1716 GSS3 - Can you answer these queries III 线段树

题目传送门:SP1043 GSS1 - Can you answer these queries I 更好的阅读体验 动态维护子段和最大值 前置知识 静态维护子段和最大值:SP1043 GSS1 - Can you answer these queries I 题解传送 题解: 提供结构体指针线段树写法: 设\(l\)为区间左端点, \(r\)为区间右端点: \(ls\)为以\(l\)为左端点的最大子段和, \(rs\)为以\(r\)为右端点的最大子段和; \(sum\)为区间和, \(val\

GSS - Can you answer these queries I ~ ? (持续更新...)

GSS - Can you answer these queries I ~ ? (持续更新...) \(\text{SPOJ}\) 毒瘤的 数据结构系列, 值得一做 GSS I : 给定一数列\(A\), 支持查询区间最大子段和 \(A[i] \le 15007,\ N\le 5e4\) 线段树常规做法 : //知识点:线段树 /* By:Luckyblock */ #include <cstdio> #include <cctype> #include <algorith