SPOJ Can you answer these queries 系列

传送门

I:Can you answer these queries I
II:Can you answer these queries II
III:Can you answer these queries III
IV:Can you answer these queries IV
V:Can you answer these queries V
VI:Can you answer these queries VI
VII:Can you answer these queries VII
VIII:Can you answer these queries VIII

题解

Can you answer these queries I

Can you answer these queries I


Can you answer these queries II

Can you answer these queries II


Can you answer these queries III

Can you answer these queries III


Can you answer these queries IV

传送门:Can you answer these queries IV
重题:洛谷 P4145 上帝造题的七分钟2 / 花神游历各国
题目描述:区间开平方运算,并区间求和
算法分析:\(\sqrt{x}\) 向下取整,那么\(\forall x \in R\),在经过有限次开平方运算后,其结果一定为\(1\)。故只需将大于\(1\)的区间的数开平方即可,就能大大降低时间复杂度,然后在更新时只要递归修改即可(\(10^{18}\)至多需要6次修改),查询时区间查询。在这里用了两个数组:\(sum\)\(maxi\)\(sum\)存储和,\(maxi\)储存区间最大值。若区间最大值 \(>1\),则需修改。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#define G ch=getchar()
#define in(x) x=read()
using namespace std;
typedef long long ll;
inline ll read()
{
    char ch=getchar();
    ll num=0,f=1;
    while((ch<'0' || ch>'9') && ch!='-') G;
    if(ch=='-') {f=-1; G;}
    while(ch>='0' && ch<='9') {num=num*10+ch-'0'; G;}
    return num*f;
}
class segment_tree
{
    #define ls k<<1
    #define rs k<<1 | 1
    #define mid ((l+r)>>1)
    #define S(x) x=(int)sqrt(x)
    #define SIZE 100000
    public:
        void clear() {memset(sum,0,sizeof(sum)); memset(maxi,0,sizeof(maxi));}
        void update(int k,int l,int r,int ql,int qr)
        {
            if(l==r) {S(sum[k]); S(maxi[k]); return;}
            if(ql<=mid && maxi[ls]>1) update(ls,l,mid,ql,qr);
            if(qr>mid && maxi[rs]>1) update(rs,mid+1,r,ql,qr);
            pushup(k);
        }
        ll query(int k,int l,int r,int ql,int qr)
        {
            if(ql<=l && r<=qr) return sum[k];
            ll ans=0;
            if(ql<=mid) ans+=query(ls,l,mid,ql,qr);
            if(qr>mid) ans+=query(rs,mid+1,r,ql,qr);
            return ans;
        }
        void build(int k,int l,int r)
        {
            if(l==r) {in(sum[k]); maxi[k]=sum[k]; return;}
            build(ls,l,mid); build(rs,mid+1,r);
            pushup(k);
        }
    private:
        ll sum[4*SIZE+1],maxi[4*SIZE+1];
        void pushup(int k) {sum[k]=sum[ls]+sum[rs]; maxi[k]=max(maxi[ls],maxi[rs]);}
    #undef ls
    #undef rs
    #undef mid
    #undef S
};
segment_tree tree;
int n,m,l,r,op,t;
void subtask(int);
int main()
{
    while(~scanf("%d",&n)) {t++; subtask(t);}
    return 0;
}
void subtask(int _case)
{
    printf("Case #%d:\n",_case);
    tree.clear();
    tree.build(1,1,n); in(m);
    for(register int i=1;i<=m;i++)
    {
        in(op); in(l); in(r);
        if(l>r) swap(l,r);
        if(op==0) tree.update(1,1,n,l,r);
        else printf("%lld\n",tree.query(1,1,n,l,r));
    }
    printf("\n");
}

Can you answer these queries V

Can you answer these queries V


Can you answer these queries VI

Can you answer these queries VI


Can you answer these queries VII

Can you answer these queries VII


Can you answer these queries VIII

Can you answer these queries VIII

posted @ 2019-02-23 22:38  常青藤的花语  阅读(238)  评论(0编辑  收藏  举报

知识共享许可协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。