zoukankan      html  css  js  c++  java
  • 水の数列

    题目链接

    观察到这样一种情况,随着数越来越大,管辖的区间的变化是:先新增一些单点区间,然后相邻的区间合并。

    于是我们可以离散化得到元素集$b_i$并更新一波$a_i$,从小到大累加着算“区间长度平方和”$sum[b_i]$。

    这里把区间的信息存在两端,每次操作新增的单点区间合并即可。

    在这期间,我们可以同时维护区间个数$c$以及$ans[c]$:相同区间个数下,最大的$dfrac{sum[b_k]}{b_k}$对应的$b_k$。

    然后关于$ans[c]$我们建一棵线段树,每次回答询问即可。注意处理好无解的情况。

    注意:算$l,r$的时候会爆$int$,建议开$long;long$并且对$n$取模。

    代码(100分):

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    #include<set>
    #define IL inline
    #define RG register
    #define _1 first
    #define _2 second
    using namespace std;
    typedef unsigned int UI;
    typedef long long LL;
    const int N=1e6;
    
    IL int read(){
        int x=0,f=1;    char ch=getchar();
        for(;!isdigit(ch);ch=getchar())if(ch=='-')    f=-1;
        for(;isdigit(ch);ch=getchar())    x=(x<<3)+(x<<1)+ch-'0';
        return x*f;
    }
    
        int n,t,a[N+3],m,b[N+3];
    
        vector<int>pos[N+3];        //a[pos[a[i]][j]]=a[i]
        int len[N+3];                //len[pos[i][j]]
        LL sum[N+3];                //sum[b[i]]=sum(^2)
        int ans[N+3];                //ans[cnt]=b[i]
        
    IL int sol(int x){
        int l=1,r=m,mid,ans;
        while(l<=r){
            mid=(l+r)>>1;
            if(x<=b[mid]){
                r=mid-1;    ans=mid;
            }
            else 
                l=mid+1;
            
        }
        return ans;
        
    }
    
    IL void pre(){
        for(int i=1;i<=n;i++)
            b[i]=a[i];
        sort(b+1,b+n+1);
        m=1;
        for(int i=2;i<=n;i++)
        if(b[i]!=b[i-1])
            b[++m]=b[i];
        for(int i=1;i<=n;i++)
            a[i]=sol(a[i]);
            
        memset(sum,-1,sizeof sum);
        memset(ans,-1,sizeof ans);
        for(int i=1;i<=n;i++)
            pos[a[i]].push_back(i);
            
        memset(len,0,sizeof len);
        int c=0;    LL s=0;
        for(int i=1;i<=m;i++){
            for(UI j=0;j<pos[i].size();j++){
                int p=pos[i][j];
                bool f1=len[p-1],f2=len[p+1];
                
                if(f1&&f2)        c--;
                if(!f1&&!f2)    c++;
                
                s++;
                if(f1)        s+=len[p-1]<<1;
                if(f2)        s+=len[p+1]<<1;
                if(f1&&f2)    s+=len[p-1]*len[p+1]<<1;
                
                len[p]=1;
                if(f1)    len[p]+=len[p-1];
                if(f2)    len[p]+=len[p+1];
                if(f1)    len[p-len[p-1]]=len[p];
                if(f2)    len[p+len[p+1]]=len[p];
                
            }
            
            sum[b[i]]=s;
            if(ans[c]==-1||s*ans[c]>sum[ans[c]]*b[i])
                ans[c]=b[i];
            
        }
        
    }
        
        LL lastans;
        
        int tr[(N<<2)+3];            //tr[]=b[i]
    
    IL int ls(int i){return i<<1;}
    IL int rs(int i){return i<<1|1;}
    
    IL bool cmp(int x,int y){
        if(x==-1)    return false;
        if(y==-1)    return true;
        return sum[x]*y>sum[y]*x;
    }
    
    IL void build(int i,int l,int r){
        if(l==r){
            tr[i]=ans[l];    return ;
        }
        
        int mid=(l+r)>>1;
        build(ls(i),l,mid);
        build(rs(i),mid+1,r);
        tr[i]=cmp(tr[ls(i)],tr[rs(i)])?tr[ls(i)]:tr[rs(i)];
        
    }
    
    IL int qry(int i,int l,int r,int ql,int qr){
        if(r<ql||qr<l)    return -1;
        if(ql<=l&&r<=qr)return tr[i];
        
        int mid=(l+r)>>1;
        if(qr<=mid)
            return qry(ls(i),l,mid,ql,qr);
        if(ql>mid)
            return qry(rs(i),mid+1,r,ql,qr);
        
        int x=qry(ls(i),l,mid,ql,qr);
        int y=qry(rs(i),mid+1,r,ql,qr);
        return cmp(x,y)?x:y;
        
    }
    
    int main(){
        n=read();    t=read();
        for(int i=1;i<=n;i++)
            a[i]=read();
        a[n+1]=1e6+1;
        
        pre();
        build(1,1,n);
        
        lastans=0;
        while(t--){
            LL aa=read()%n,bb=read()%n,xx=read()%n,yy=read()%n;
            int l=(aa*lastans+xx-1+(n<<1))%n+1;
            int r=(bb*lastans+yy-1+(n<<1))%n+1;
            if(l>r)    swap(l,r);
        
            int ansx=qry(1,1,n,l,r);
            LL anssum=ansx==-1?-1:sum[ansx];
            printf("%lld %d
    %d %d %lld
    ",anssum,ansx,l,r,lastans%n);
            lastans=anssum%n*ansx%n;
            
        }
    
        return 0;
    
    }
    View Code
  • 相关阅读:
    一篇好文,以在迷茫时阅读
    [转]EeeBox 安裝 Debian 後驅動 Wireless 筆記
    SVN内外网版本库同步手册
    Android小试牛刀之1——对话框应用和SharedPeferences存储
    关于Lucene.net 2.9.2.2 中删除索引的若干问题
    提高SQL SERVER并发能力
    Entity Framework 4 Poco开发之旅 part 2
    在linux下安装dropbox
    Windows平台高性能站点手册
    利用java反射原理写了一个简单赋值和取值通用类【改】
  • 原文地址:https://www.cnblogs.com/Hansue/p/12920210.html
Copyright © 2011-2022 走看看