zoukankan      html  css  js  c++  java
  • 洛谷P4145上帝造题的七分钟——区间修改

    题目:https://www.luogu.org/problemnew/show/P4145

    区间开平方,可以发现其实开几次就变成1,不需要开了,所以标记一下,每次只去开需要开的地方;

    原来写的并查集跳过1或0,然而WA...其实是没有记录原数组的值,因为树状数组存的是修改量;

    (如果a数组<原数组>开int会RE!)

    改成线段树,本来想着是这一段区间和只要小于等于其长度就可以跳过了,然而仔细想想完全不是,应为可能有多个0什么的;

    所以直接开bool数组标记一下就好了;

    不需要pushdown,直接去修改或是跳过。

    并查集:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    int const MAXN=100005;
    int n,m,a[MAXN],fa[MAXN];
    ll f[MAXN];
    int find(int x)
    {
        if(x==fa[x])return x;
        return fa[x]=find(fa[x]);
    }
    void add(int x,ll y)
    {
        for(;x<=n;x+=(x&-x))
            f[x]+=y;
    }
    void update(int x)
    {
        int tmp=a[x];
        a[x]=sqrt(a[x]);
        if(a[x]==1||a[x]==0)fa[x]=find(x+1);
        add(x,a[x]-tmp);
    //    for(;x<=n;x+=(x&-x))
    //        f[x]-=tmp,f[x]+=a[x];
    }
    ll query(int x)
    {
    //    for(int i=1;i<=n;i++)
    //        printf("%d ",a[i]);
    //    printf("
    ");
        ll sum=0;
        for(;x;x-=(x&-x))
            sum+=f[x];
        return sum;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            fa[i]=i;
            add(i,a[i]);
        }
    //    for(int i=1;i<=n;i++)
    //        printf("%lld ",f[i]);
    //    printf("
    ");
        fa[n+1]=n+1;
        scanf("%d",&m);
        while(m--)
        {
            int t,l,r;
            scanf("%d%d%d",&t,&l,&r);
            if(l>r)swap(l,r);
            if(t==0)
            {
                int x=find(l);
                while(x<=r)
                {
                    update(x);
                    x=find(x+1);
    //                cout<<x<<endl;
                }
            }
            if(t==1)
            {
                ll s1=0,s2=0;
                if(l-1)s1=query(l-1);
                s2=query(r);
    //            printf("s1=%lld s2=%lld
    ",s1,s2);
                printf("%lld
    ",s2-s1);
            }
        }
        return 0;
    }

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    int const MAXN=100005;
    int n,m;
    ll tr[MAXN<<2],a[MAXN];
    bool tg[MAXN<<2];
    void pushup(int nw)
    {
        tr[nw]=tr[nw<<1]+tr[nw<<1|1];
        tg[nw]=(tg[nw<<1]&&tg[nw<<1|1]);
    }
    //void pushdown(int l,int r,int nw)
    //{
    //    if(l==r)
    //    {
    //        tr[nw]=sqrt(tr[nw]);
    //        return;
    //    }
    //    while(lz[nw])
    //    {
    //        if(tr[nw]<=r-l+1)
    //        {
    //            lz[nw]=0;
    //            break;
    //        }
    //        int mid=((l+r)>>1);
    //        if(tr[nw<<1]>mid-l+1)pushdown(l,mid,nw<<1);
    //        if(tr[nw<<1|1]>r-mid)pushdown(mid+1,r,nw<<1|1);
    //        pushup(nw);
    //        lz[nw]--;
    //    }
    //}
    void update(int l,int r,int L,int R,int nw)
    {
        if(tg[nw])return;
        if(l==r)
        {
            tr[nw]=(ll)sqrt(tr[nw]);
            if(tr[nw]==1||tr[nw]==0)tg[nw]=1;
            return;
        }
        int mid=((l+r)>>1);
        if(mid>=L)update(l,mid,L,R,nw<<1);
        if(mid<R)update(mid+1,r,L,R,nw<<1|1);
        pushup(nw);
    }
    ll query(int l,int r,int L,int R,int nw)
    {
    //    for(int i=1;i<=n;i++)
    //        printf("%d ",a[i]);
    //    printf("
    ");
        ll sum=0;
        if(l>=L&&r<=R)
        {
    //        pushdown(l,r,nw);
            return tr[nw];
        }
        int mid=((l+r)>>1);
        if(mid>=L)sum+=query(l,mid,L,R,nw<<1);
        if(mid<R)sum+=query(mid+1,r,L,R,nw<<1|1);
        return sum;
    }
    void build(int l,int r,int nw)
    {
        if(l==r)
        {
            tr[nw]=a[l];
            if(a[l]==1||a[l]==0)tg[nw]=1;
            return;
        }
        int mid=((l+r)>>1);
        build(l,mid,nw<<1);
        build(mid+1,r,nw<<1|1);
        pushup(nw);
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%lld",&a[i]);
        scanf("%d",&m);
        build(1,n,1);
        while(m--)
        {
            int d,x,y;
            scanf("%d%d%d",&d,&x,&y);
            if(x>y)swap(x,y);
            if(d==0)update(1,n,x,y,1);
            if(d==1)printf("%lld
    ",query(1,n,x,y,1));
        }
        return 0;
    }
  • 相关阅读:
    堆栈之链表实现
    队列之数组实现
    堆栈之数组实现
    线性表之循环双链表
    GMAP 集合已修改;可能无法执行枚举操作 错误【正解】(原创)
    大智慧选股公式
    获取股票实时交易数据的方法
    GMAP谷歌地图的纠偏 保密算法
    GMAP 判断一个坐标点是否在不规则多边形内部的算法
    SQL快速操作技巧2_datatable批量更新到数据表
  • 原文地址:https://www.cnblogs.com/Zinn/p/8759211.html
Copyright © 2011-2022 走看看