zoukankan      html  css  js  c++  java
  • HDU 5828 Rikka with Sequence

    好久没写线段树了,这题作为一个回味..

    第一种操作的话,就是一个延迟标记。

    第二种操作可以暴力更新下去,但是有一个优化,如果某区间内所有值都是一样的,或者最大值和最小值相差1,那么到此结束,不要继续往下面更新了。

    这样一来的话,pushDown的时候要注意一下,如果该区间内所有值都一样,或者最大值和最小值相差1那么延迟标记不要往下扔了,直接把该区间的信息传下去。如果该区间内所有值不一样,将延迟标记扔下去。

    总体难度不算大,仔细一些就能AC。

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<set>
    #include<queue>
    #include<stack>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    const double pi=acos(-1.0),eps=1e-8;
    void File()
    {
        freopen("D:\in.txt","r",stdin);
        freopen("D:\out.txt","w",stdout);
    }
    template <class T>
    inline void read(T &x) {
        char c = getchar(); x = 0;while(!isdigit(c)) c = getchar();
        while(isdigit(c)) { x = x * 10 + c - '0'; c = getchar();  }
    }
    
    const int maxn=100000+10;
    struct Seg { LL sum,f,MAX,MIN; }s[4*maxn];
    int T,n,m;
    
    void pushUp(int rt)
    {
        s[rt].sum=s[2*rt].sum+s[2*rt+1].sum;
        s[rt].MAX=max(s[2*rt].MAX,s[2*rt+1].MAX);
        s[rt].MIN=min(s[2*rt].MIN,s[2*rt+1].MIN);
    }
    
    void pushDown(int l,int r,int rt)
    {
        if(s[rt].MIN==s[rt].MAX)
        {
            s[2*rt].MIN=s[2*rt+1].MIN=s[rt].MIN;
            s[2*rt].MAX=s[2*rt+1].MAX=s[rt].MAX;
    
            int fz=(l+r)/2-l+1;
            s[2*rt].sum=(LL)fz*s[rt].MIN;
            s[2*rt+1].sum=s[rt].sum-s[2*rt].sum;
            s[rt].f=s[2*rt].f=s[2*rt+1].f=0;
            return;
        }
    
        if(s[rt].MIN==s[rt].MAX-1)
        {
            int Tmin=min(s[2*rt].MIN,s[2*rt+1].MIN),Tmax=max(s[2*rt].MAX,s[2*rt+1].MAX);
    
            int len,x1,x2;
            if(s[2*rt].MIN==s[2*rt].MAX)
            {
                if(s[2*rt].MIN==Tmin) s[2*rt].MIN=s[2*rt].MAX=s[rt].MIN;
                else s[2*rt].MIN=s[2*rt].MAX=s[rt].MAX;
                s[2*rt].sum=(LL)((l+r)/2-l+1)*s[2*rt].MIN;
            }
            else
            {
                len=(l+r)/2-l+1;
                x1=(s[2*rt].sum-s[2*rt].MAX*(LL)len)/(s[2*rt].MIN-s[2*rt].MAX); x2=len-x1;
                s[2*rt].MAX=s[rt].MAX; s[2*rt].MIN=s[rt].MIN;
                s[2*rt].sum=(LL)x1*s[2*rt].MIN+(LL)x2*s[2*rt].MAX;
            }
    
            if(s[2*rt+1].MIN==s[2*rt+1].MAX)
            {
                if(s[2*rt+1].MIN==Tmin) s[2*rt+1].MIN=s[2*rt+1].MAX=s[rt].MIN;
                else s[2*rt+1].MIN=s[2*rt+1].MAX=s[rt].MAX;
                s[2*rt+1].sum=(r-(l+r)/2)*s[2*rt+1].MIN;
            }
            else
            {
                len=r-(l+r)/2;
                x1=(s[2*rt+1].sum-s[2*rt+1].MAX*(LL)len)/(s[2*rt+1].MIN-s[2*rt+1].MAX); x2=len-x1;
                s[2*rt+1].MAX=s[rt].MAX; s[2*rt+1].MIN=s[rt].MIN;
                s[2*rt+1].sum=(LL)x1*s[2*rt+1].MIN+(LL)x2*s[2*rt+1].MAX;
            }
            s[rt].f=s[2*rt].f=s[2*rt+1].f=0;
            return;
        }
    
        if(s[rt].f==0) return;
    
        s[2*rt].f=s[2*rt].f+s[rt].f;
        s[2*rt+1].f=s[2*rt+1].f+s[rt].f;
    
        s[2*rt].MAX=s[2*rt].MAX+s[rt].f;
        s[2*rt+1].MAX=s[2*rt+1].MAX+s[rt].f;
    
        s[2*rt].MIN=s[2*rt].MIN+s[rt].f;
        s[2*rt+1].MIN=s[2*rt+1].MIN+s[rt].f;
    
        int m=(l+r)/2;
        s[2*rt].sum=s[2*rt].sum+(LL)(m-l+1)*s[rt].f;
        s[2*rt+1].sum=s[2*rt+1].sum+(LL)(r-m)*s[rt].f;
    
        s[rt].f=0;
    }
    
    void build(int l,int r,int rt)
    {
        s[rt].f=0; s[rt].MAX=0; s[rt].MIN=0; s[rt].sum=0;
        if(l==r)
        {
            read(s[rt].sum);
            s[rt].f=0; s[rt].MAX=s[rt].sum; s[rt].MIN=s[rt].sum;
            return;
        }
        int m=(l+r)/2;
        build(l,m,2*rt);
        build(m+1,r,2*rt+1);
        pushUp(rt);
    }
    
    void add(int L,int R,int x,int l,int r,int rt)
    {
        if(L<=l&&r<=R)
        {
            s[rt].f=s[rt].f+x; s[rt].MAX=s[rt].MAX+x;
            s[rt].MIN=s[rt].MIN+x; s[rt].sum=s[rt].sum+(r-l+1)*(LL)x;
            return;
        }
        pushDown(l,r,rt);
        int m=(l+r)/2;
        if(L<=m) add(L,R,x,l,m,2*rt);
        if(R>m)  add(L,R,x,m+1,r,2*rt+1);
        pushUp(rt);
    }
    
    LL quary(int L,int R,int l,int r,int rt)
    {
        if(L<=l&&r<=R) return s[rt].sum;
        pushDown(l,r,rt);
        int m=(l+r)/2; LL x1=0,x2=0;
        if(L<=m) x1=quary(L,R,l,m,2*rt);
        if(R>m)  x2=quary(L,R,m+1,r,2*rt+1);
        pushUp(rt);
        return x1+x2;
    }
    
    void force(int l,int r,int rt)
    {
        if(l==r)
        {
            s[rt].sum=(LL)sqrt(1.0*s[rt].sum);
            s[rt].MIN=s[rt].MAX=s[rt].sum;
            return;
        }
        if(s[rt].MIN==s[rt].MAX)
        {
            s[rt].MAX=s[rt].MIN=(LL)sqrt(1.0*s[rt].MIN);
            s[rt].sum=(LL)(r-l+1)*s[rt].MIN;
            return;
        }
    
        if(s[rt].MIN==s[rt].MAX-1)
        {
            int len=r-l+1;
            int x1=(s[rt].sum-s[rt].MAX*(LL)len)/(s[rt].MIN-s[rt].MAX), x2=len-x1;
            s[rt].MAX=(LL)sqrt(1.0*s[rt].MAX);
            s[rt].MIN=(LL)sqrt(1.0*s[rt].MIN);
            s[rt].sum=(LL)x1*s[rt].MIN+(LL)x2*s[rt].MAX;
    
            return;
        }
    
        pushDown(l,r,rt);
        int m=(l+r)/2;
        if(s[2*rt].MAX!=1) force(l,m,2*rt);
        if(s[2*rt+1].MAX!=1) force(m+1,r,2*rt+1);
        pushUp(rt);
    }
    
    void update(int L,int R,int l,int r,int rt)
    {
        if(L<=l&&r<=R) { if(s[rt].MAX==1) return; force(l,r,rt); return; }
        pushDown(l,r,rt);
        int m=(l+r)/2;
        if(L<=m&&s[2*rt].MAX!=1) update(L,R,l,m,2*rt);
        if(R>m&&s[2*rt+1].MAX!=1) update(L,R,m+1,r,2*rt+1);
        pushUp(rt);
    }
    
    int main()
    {
        scanf("%d",&T); while(T--)
        {
            read(n); read(m); build(1,n,1);
            for(int i=1;i<=m;i++)
            {
                int op,L,R,x;
                read(op); read(L); read(R);
                if(op==1) { read(x); add(L,R,x,1,n,1); }
                else if(op==2) update(L,R,1,n,1);
                else if(op==3) printf("%lld
    ",quary(L,R,1,n,1));
            }
        }
        return 0;
    }
  • 相关阅读:
    由Highcharts加载提示想到的:我想要的别人已经做好了
    ajaxmin js压缩和VS(转1)
    ajaxmin js压缩和VS(转2)
    Silverlight客户端怎样获取外部参数
    SQL中的事务
    qt webkit 中文乱码问题 另辟蹊径
    密码学基础(1)
    使用jQuery的属性[attr]筛选
    Leetcode NO.19 Remove Nth Node From End Of List && 移除链表倒数第n个节点
    经典排序算法(一) —— Selection Sort 选择排序
  • 原文地址:https://www.cnblogs.com/zufezzt/p/5763081.html
Copyright © 2011-2022 走看看