SP2713 GSS4 - Can you answer these queries IV

传送门



\(ZHX\; TQL\) Orz



这道题目我们可以用线段树维护……

可能有\(dalao\)会问:“线段树怎么维护区间开平方?”

而这道题的精髓就在于,它要我们维护的操作是开平方+下取整。也就是说经过一定的次数,要开平方的数会慢慢缩小为"\(1\)",这个次数是很小的,而\(\sqrt 1=1\)。

所以在修改时,我们可以先查询这个区间是否全是"1",如果是,那我们就不管它,再去寻找其他的区间进行修改,如果这个区间里有其他数,我们就将这些递归寻找这些数,然后单点修改进行开平方操作。

\(\tt{P.S.}\) 要注意这个题目的输出格式

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define mid ((l+r)>>1)
#define LL long long
#define ls p<<1
#define rs p<<1|1
using namespace std;
LL tree[100010<<4],a[100010];
inline void up(int p){
    tree[p]=tree[ls]+tree[rs];
}
void build(int l,int r,int p){
    if(l==r){
        tree[p]=a[l]; return ;
    }
    build(l,mid,ls); build(mid+1,r,rs);
    up(p);
}
void update(int l,int r,int p,int nl,int nr){
    if(l>=nl&&r<=nr){
        if(tree[p]<=r-l+1) return ;
        else{
            if(l==r){
                tree[p]=(int)sqrt((double)tree[p]);
                return ;
            }
        }
    }
    up(p);
    if(nl<=mid) update(l,mid,ls,nl,nr);
    up(p);
    if(nr>mid) update(mid+1,r,rs,nl,nr);
    up(p);
}
LL query(int l,int r,int p,int nl,int nr){
    LL ans=0;
    if(l>=nl&&r<=nr) return tree[p];
    if(nl<=mid) ans+=query(l,mid,ls,nl,nr);
    if(nr>mid) ans+=query(mid+1,r,rs,nl,nr);
    return ans;
}
LL read(){
    LL k=0,f=1; char c=getchar();
    for(;c<'0'||c>'9';c=getchar())
      if(c=='-') f=-1;
    for(;c>='0'&&c<='9';c=getchar())
      k=k*10+c-48;
    return k*f;
}
int main(){
    //freopen("hh.in","r",stdin);
    //freopen("hh.out","w",stdout);
    int n,tot=0;
    while(scanf("%d\n",&n)!=EOF){
        printf("Case #%d:\n",++tot);
        for(int i=1;i<=n;i++) a[i]=read();
        build(1,n,1);
        int m=read();
        for(int i=1;i<=m;i++){
            int k=read(),l=read(),r=read();
            if(l>r) swap(l,r);
            if(k==0) update(1,n,1,l,r);
            else printf("%lld\n",query(1,n,1,l,r));
        }
        printf("\n");
    }
    return 0;
}

原文地址:https://www.cnblogs.com/wxl-Ezio/p/9593582.html

时间: 2024-10-09 11:10:30

SP2713 GSS4 - Can you answer these queries IV的相关文章

【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

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

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

HDU4027 Can you answer these queries 线段树区间求和+剪枝

给了你n,然后n个数字在一个数组中,接下来m个询问,每个询问三个数字 t,x,y,若t==0,那么修改区间[x,y]的每一个值,变为原来每个位置上的数 开根号取整,若t==1,那么对区间[x,y]求和 由于n,m,很大,所以树状数组铁定超时,若直接用线段树来做区间修改,那么也是超时,这类题目没别的方法了,静心剪枝,发现题目给的数据范围为2^63,有没有发现,2^63开根号 绝对不需要开10次,就能到1,到1以后就不需要再开了,意思就是若有某个区间[x,y]每一个点的值都为1时,这一段区间事实上是