ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

养花

2020-11-15 17:32:10  阅读:152  来源: 互联网

标签:node 养花 return log int mid 2n


[模拟赛] 养花


\(对于 100\% 的数据, n ≤ 10^5,m ≤ 10^5,a_i ≤ 10^5,k_i ≤ 10^5。\)

思路:

考虑2种暴力做法(下文中默认n,m,a,值域同阶)

  1. 对于每个k,处理出%k意义下的区间最大值,直接查询即可,时间复杂度为\(O(n^2+n\log_2n)\)
  2. 对于每个k,枚举商数i,查询区间内满足值除以k(下取整)等于i的最大值,使用主席树维护。时间复杂度为\(O(n\frac{n}{k}\log_2n)\)

从上面可以看出,暴力2在k很大时效率很高,所以我们考虑2种暴力混合使用。

我们先处理出每个\(k<=W\)的线段树(暴力1),当询问\(k \leq w\)时线段树上查询;否则使用暴力2

时间复杂度为\(O(Wn+\frac{n}{W}n\log_2n)\)

\(O(Wn+\frac{n}{W}n\log_2n)\geq O(n\sqrt{n\log_2n})\),当\(W=\sqrt{n\log_2n}\)时取等

\[\mathfrak{Talk\ is\ cheap,show\ you\ the\ code.} \]

#include<bits/stdc++.h>
using namespace std;
# define ll long long
# define Type template<typename T>
# define read read1<ll>()
Type T read1(){
    T t=0;
    char k;
    bool vis=0;
    do (k=getchar())=='-'&&(vis=1);while('0'>k||k>'9');
    while('0'<=k&&k<='9')t=(t<<3)+(t<<1)+(k^'0'),k=getchar();
    return vis?-t:t;
}
# define fre(k) freopen(k".in","r",stdin);freopen(k".out","w",stdout) 
# define SQ 1303
int s,m,a[100005],v[400005],ans[100005];
struct Q{
    int l,r,n;
};
struct node{
    node *l,*r;
    int t;
    node(){l=r=NULL;t=0;}
}*root[100005];
vector<Q>q[100005];
node* L(node *x){return x?x->l:NULL;}
node* R(node *x){return x?x->r:NULL;}
node* ins(node* x,int l,int r,int v){
    node* n=new node();
    if(x)n->l=x->l,n->r=x->r,n->t=x->t;
    ++n->t;
    if(l==r)return n;
    int mid=l+r>>1;
    if(v<=mid)n->l=ins(L(n),l,mid,v);
    else n->r=ins(R(n),mid+1,r,v);
    return n;
}
void build(int l,int r,int d,int& k){
    if(l==r)v[d]=a[l]%k;
    else{//mumumei momom
        int mid=l+r>>1;
        build(l,mid,d<<1,k);
        build(mid+1,r,d<<1|1,k);
        v[d]=max(v[d<<1],v[d<<1|1]);
    }
}
int query(int l,int r,int tl,int tr,int d){
    if(l==tl&&r==tr)return v[d];
    int mid=l+r>>1;
    if(tr<=mid)return query(l,mid,tl,tr,d<<1);
    if(mid<tl)return query(mid+1,r,tl,tr,d<<1|1);
    return max(query(l,mid,tl,mid,d<<1),query(mid+1,r,mid+1,tr,d<<1|1));
}
int SZ(node *x){return x?x->t:0;}
int query(node *x,node *y,int l,int r,int tl,int tr){
    if(SZ(x)==SZ(y))return -1;
    if(tl==tr)return tl;
    int mid=tl+tr>>1;
    if(r<=mid)return query(L(x),L(y),l,r,tl,mid);
    if(mid<l)return query(R(x),R(y),l,r,mid+1,tr);
    int v=query(R(x),R(y),mid+1,r,mid+1,tr);
    if(~v)return v;
    return query(L(x),L(y),l,mid,tl,mid);
}
int main(){
    // fre("flower");
    s=read,m=read;
    for(int i=1;i<=s;++i)
        root[i]=ins(root[i-1],1,100001,a[i]=read);
    for(int i=1;i<=m;++i){
        Q tem;tem.l=read,tem.r=read,tem.n=i;
        q[read].push_back(tem);
    }
    for(int i=1;i<=SQ;++i)
        if(q[i].size()){
            build(1,s,1,i);
            for(int j=0;j<q[i].size();++j){
                ans[q[i][j].n]=query(1,s,q[i][j].l,q[i][j].r,1);
            }
        }
    for(int j=SQ+1;j<=100001;++j){
        for(int i=0;i<=100001/j;++i){
            int l=i*j,r=(i+1)*j-1;if(r>100001)r=100001;
            if(l<1)l=1;
            for(int k=0;k<q[j].size();++k)
                ans[q[j][k].n]=max(ans[q[j][k].n],query(root[q[j][k].l-1],root[q[j][k].r],l,r,1,100001)-i*j);
        }
    }
    for(int i=1;i<=m;++i)printf("%d\n",ans[i]);
    return 0;
}

标签:node,养花,return,log,int,mid,2n
来源: https://www.cnblogs.com/SYDevil/p/13977521.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有