其他分享
首页 > 其他分享> > 未曾设想的道路(线段树)

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

作者:互联网

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

 

标签:未曾,int,线段,设想,最大值,v1,v2,rep,define
来源: https://www.cnblogs.com/yinwuxiao/p/14862300.html