zoukankan      html  css  js  c++  java
  • P4145 上帝造题的七分钟2 / 花神游历各国

    简单明了。直接数据结构了。

    算了还是先想想暴力吧。。。

    暴力开根,暴力求和目测30pts....

    或许可以用树状数组维护前缀和??目测满分.....(维护前缀和,用并查集跳过已经是1的点)

    我还是想练练线段树,那就讲讲线段树写法吧

    首先,没有区间加,不用lazy_tag。

    其次,看数据范围,最大的数开方不超过6次就会变成1(其实这个东西对解题没什么帮助233)

    记录一个区间最大值,这样,当它都等于1了,那么区间里其他小于它的数都已经变成1了,

    所有就可以暴力单点改了。

    在开根的时候,对于最大值也要进行开根处理,然后单点改和区间查就一样了。

    代码也比较短:

    坑点:本蒟蒻在写的时候把区间查也写成了单点查(从叶子结点向上合并),导致了40pts(TLE*6)的好成绩。

    l和r顺序不一定对(建议以后都加上一句swap)

    #include<bits/stdc++.h>
    #define lch(x) x<<1
    #define rch(x) x<<1|1
    using namespace std;
    const long long maxn=100010;
    long long a[maxn];
    long long n,m;
    struct tree
    {
        long long sum,s;
        long long l,r;
    }t[maxn<<2];
    void update(long long p)
    {
        t[p].sum=t[lch(p)].sum+t[rch(p)].sum;
        t[p].s=max(t[lch(p)].s,t[rch(p)].s);
    }
    void build(long long l,long long r,long long p)
    {
        t[p].l=l;
        t[p].r=r;
        if(l==r)
        {
            t[p].sum=t[p].s=abs(a[l]);
            return;
        }
        long long mid=l+r>>1;
        build(l,mid,lch(p));
        build(mid+1,r,rch(p));
        update(p);
    }
    void change(long long l,long long r,long long p)
    {
        if(t[p].l==t[p].r)
        {
            t[p].sum=sqrt(t[p].sum);
            t[p].s=sqrt(t[p].s);
            return;
        }
        long long mid=t[p].l+t[p].r>>1;
        if(l<=mid&&t[p].s>1)
        change(l,r,lch(p));
        if(r>mid&&t[p].s>1)
        change(l,r,rch(p));
        update(p);
    }
    long long ask(long long l,long long r,long long p)
    {
        if(l<=t[p].l&&t[p].r<=r)
        {
            return t[p].sum;
        }
        long long mid=t[p].l+t[p].r>>1;
        long long ans=0;
        if(l<=mid)
        ans+=ask(l,r,lch(p));
        if(r>mid)
        ans+=ask(l,r,rch(p));
        return ans;
    }
    int main()
    {
        scanf("%lld",&n);
        for(long long i=1;i<=n;i++)
        {
            scanf("%lld",&a[i]);
        }
        build(1,n,1);
        scanf("%lld",&m);
        while(m--)
        {
            long long flag,x,y;
            scanf("%lld%lld%lld",&flag,&x,&y);
            if(x>y)
            swap(x,y);
            if(flag==0)
            {
                change(x,y,1);
            }
            if(flag==1)
            {
                printf("%lld
    ",ask(x,y,1));
            }
        }
        return 0;
    }

    (完)

  • 相关阅读:
    现在分词做状语,到,非谓语动词
    成功和失败因素收集
    退拽原理2
    分享到(事件冒泡实例)
    滚动公告(纵向)
    RabbitMQ消息队列(一): Detailed Introduction 详细介绍
    在IDEA中实战Git
    深入浅出JMS(三)--ActiveMQ简单的HelloWorld实例
    MySQL中日期和时间戳互相转换的函数和方法
    【Docker】 windows10 docker 使用
  • 原文地址:https://www.cnblogs.com/ajmddzp/p/11397643.html
Copyright © 2011-2022 走看看