• 未曾设想的道路(线段树)


    https://ac.nowcoder.com/acm/contest/11244/C

    题解:

    考虑只需要区间修改,求历史最大值

    那么用线段树的话我们需要维护历史标记最大值,当前标记,区间当前最大值,历史区间最大值

    其实现在变成求历史K大可以类似维护

    我们维护历史标记最大的K个,当前标记,区间当前最大的K个,区间历史最大的K个

    这样子updata的时候是比较显然的两个数组扫一下 复杂度O(logn*K)

    down的时候一方面要维护历史标记最大值,这个是O(logn*K)的

    另一方面要更新历史区间最大值,这是个堆的经典问题 复杂度O(logn*logk*k)

    所以总时间复杂度O(nlognK+mlogn*logk*k)

    因为down是瓶颈注意标记判一下有标记再down

    代码:

    #pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
    #pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native")
    
    //#include <immintrin.h>
    //#include <emmintrin.h>
    #include <bits/stdc++.h>
    using namespace std;
    #define rep(i,h,t) for (int i=h;i<=t;i++)
    #define dep(i,t,h) for (int i=t;i>=h;i--)
    #define ll long long
    #define me(x) memset(x,0,sizeof(x))
    #define mep(x,y) memcpy(x,y,sizeof(y))
    #define IL inline
    #define rint register int
    #define mp make_pair
    inline ll rd(){
        ll x=0;char c=getchar();bool f=0;
        while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        return f?-x:x;
    }
    char ss[1<<24],*A=ss,*B=ss;
    IL char gc()
    {
        return A==B&&(B=(A=ss)+fread(ss,1,1<<24,stdin),A==B)?EOF:*A++;
    }
    template<class T>void maxa(T &x,T y)
    {
        if (y>x) x=y;
    }
    template<class T>void mina(T &x,T y)
    {
        if (y<x) x=y;
    }
    template<class T>void read(T &x)
    {
        int f=1,c; while (c=gc(),c<48||c>57) if (c=='-') f=-1; x=(c^48);
        while(c=gc(),c>47&&c<58) x=x*10+(c^48); x*=f;
    }
    const int mo=1e9+7;
    ll fsp(int x,int y)
    {
        if (y==1) return x;
        ll ans=fsp(x,y/2);
        ans=ans*ans%mo;
        if (y%2==1) ans=ans*x%mo;
        return ans;
    }
    struct cp {
        ll x,y;
        cp operator +(cp B)
        {
            return (cp){x+B.x,y+B.y};
        }
        cp operator -(cp B)
        {
            return (cp){x-B.x,y-B.y};
        }
        ll operator *(cp B)
        {
            return x*B.y-y*B.x;
        }
        int half() { return y < 0 || (y == 0 && x < 0); }
    };
    struct re{
        int a,b,c;
    };
    const int N=1.1e5;
    int a[N];
    const int Mx=100;
    #define mid ((h+t)/2)
    struct sgt{
        int v1[N*4][101],v2[N*4][101],lz1[N*4],lz[N*4][101];
        sgt()
        {
            rep(i,0,N*4-1)
            {
              rep(j,0,100) v2[i][j]=lz[i][j]=v1[i][j]=-1e9;
              v1[i][1]=0;
            }
        }
        inline void g(int *a,int *b)
        {
            int c[101];
            int x=1,y=1;
            rep(i,1,Mx)
              if (a[x]>b[y]) c[i]=a[x++];
              else c[i]=b[y++];
            mep(a,c);
        }
        inline void updata(int x)
        {
            mep(v2[x],v2[x*2]);
            g(v2[x],v2[x*2+1]);
            mep(v1[x],v1[x*2]);
            g(v1[x],v1[x*2+1]);
        }
        void build(int x,int h,int t)
        {
            if (h==t)
            {
                v1[x][1]=v2[x][1]=a[h];
                return;
            }
            build(x*2,h,mid); build(x*2+1,mid+1,t);
            updata(x);
        }
        inline void g2(int *a,int *b,int *c)
        {
            priority_queue<pair<int,int> > M; 
            int h[101];
            rep(i,1,Mx) M.push(mp(b[i]+c[1],i)),h[i]=1;
            rep(i,1,Mx)
            {
                auto x=M.top();
                a[i]=max((int)(-1e9),x.first);
                M.pop();
                int y=x.second;
                h[y]++;
                M.push(mp(b[y]+c[h[y]],y));
            }
        }
        inline void down(int x)
        {
            if (lz[x][1]>-1e8)
            {
              rep(r,x*2,x*2+1)
              {
                int b[101];
                rep(i,1,Mx) b[i]=lz[x][i]+lz1[r];
                g(lz[r],b);
                lz1[r]+=lz1[x];
                g2(b,v1[r],lz[x]);
                g(v2[r],b);
                rep(i,1,Mx) v1[r][i]=v1[r][i]+lz1[x];
              }
              lz1[x]=0;
              rep(i,1,Mx) lz[x][i]=-1e9;
            }
        }
        void add(int x,int h,int t,int h1,int t1,int k)
        {
            if (h1<=h&&t<=t1)
            {
                lz1[x]+=k;
                int h[101];
                h[1]=lz1[x]; rep(i,2,100) h[i]=-1e9;
                g(lz[x],h);
                rep(i,1,Mx) v1[x][i]=v1[x][i]+k;
                g(v2[x],v1[x]);
                return;
            }
            down(x);
            if (h1<=mid) add(x*2,h,mid,h1,t1,k);
            if (mid<t1) add(x*2+1,mid+1,t,h1,t1,k);
            updata(x);
        }
        void query(int x,int h,int t,int h1,int t1,int *a)
        {
            if(h1<=h&&t<=t1)
            {
                g(a,v2[x]); return;
            }
            down(x);
            if (h1<=mid) query(x*2,h,mid,h1,t1,a);
            if (mid<t1) query(x*2+1,mid+1,t,h1,t1,a);
        }
    }S;
    int main()
    {
       freopen("11.in","r",stdin);
       freopen("11.out","w",stdout);
       ios::sync_with_stdio(false);
       int n,m;
       cin>>n>>m;
       rep(i,1,n) cin>>a[i];
       S.build(1,1,n);
      /* rep(i,1,n)
       { 
         if (i==2e4) return 0;
         cout<<i<<endl;
         S.add(1,1,n,i,i,a[i]);
       } */
       //return 0;
       rep(i,1,m)
       {
       //    if (i%100==0) cerr<<i<<endl;
            int kk,l,r,x;
            cin>>kk>>l>>r>>x;
            if (kk==0) S.add(1,1,n,l,r,x);
            else
            {
                int ans[101];
                rep(i,1,100) ans[i]=-1e9;
                S.query(1,1,n,l,r,ans);
                int pp;
            //    rep(i,1,x) cout<<ans[i]<<" ";
           //     cout<<endl;
                rep(i,1,x) if (ans[i]>-1e8) pp=ans[i];
                cout<<pp<<endl;
            }
       }
       return 0;
    }
    View Code
  • 相关阅读:
    javaweb请求编码 url编码 响应编码 乱码问题 post编码 get请求编码 中文乱码问题 GET POST参数乱码问题 url乱码问题 get post请求乱码 字符编码
    windows查看端口占用 windows端口占用 查找端口占用程序 强制结束端口占用 查看某个端口被占用的解决方法 如何查看Windows下端口占用情况
    javaWeb项目中的路径格式 请求url地址 客户端路径 服务端路径 url-pattern 路径 获取资源路径 地址 url
    ServletRequest HttpServletRequest 请求方法 获取请求参数 请求转发 请求包含 请求转发与重定向区别 获取请求头字段
    HttpServletResponse ServletResponse 返回响应 设置响应头设置响应正文体 重定向 常用方法 如何重定向 响应编码 响应乱码
    Servlet主要相关类核心类 容器调用的过程浅析 servlet解读 怎么调用 Servlet是什么 工作机制
    linq查询语句转mongodb
    winddows rabbitmq安装与配置
    Redis For Windows安装及密码
    出现,视图必须派生自 WebViewPage 或 WebViewPage错误解决方法
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/14862300.html
Copyright © 2020-2023  润新知