P5012 水の数列

P5012 水の数列

离线处理出选择每个数得到区间数得到刚开始的得分

(RMQ_{ij})表示(i)~(i)+(2^j)-1的区间最大值

#include<cstdio>
#include<vector>
using namespace std;
typedef long long LL;
const LL maxn=1e6+10;
inline LL Read(){
    LL x=0,f=1; char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-') f=-1; c=getchar();
    }
    while(c>='0'&&c<='9'){
        x=(x<<3)+(x<<1)+c-'0'; c=getchar();
    }return x*f;
}
LL n,m;
LL ans[maxn],len[maxn],lg[maxn>>1],a[maxn];
int RMQ[maxn>>1][20];
inline LL Chkmax(LL x,LL y){
    if(!x||!y)
        return x+y;
    if(ans[x]*y>ans[y]*x)
        return x;
    else if(ans[y]*x,ans[x]*y)
        return y;
    else
        return (x>y)?x:y;
}
vector<LL> vec[maxn];
inline void First(){
    LL up=0;
    for(LL i=1;i<=n;++i)
        vec[a[i]].push_back(i),
        up=max(up,a[i]);
    LL val=0,cnt=0;
    for(LL i=1;i<=up;++i){
        if(!vec[i].size())
            continue;
        for(LL j=0;j<vec[i].size();++j){
        	LL v=vec[i][j];
        	if(!len[v+1]&&!len[v-1]){
        		++val;
        		++cnt;
        		len[v]=1;
            }else if(len[v+1]&&len[v-1]){
                val+=2*len[v+1]*len[v-1]+2*len[v+1]+2*len[v-1]+1;
                --cnt;
                len[v-len[v-1]]=len[v+len[v+1]]=len[v-1]+len[v+1]+1;
            }else if(len[v-1]){
                val+=2*len[v-1]+1;
                len[v-len[v-1]]=len[v]=len[v-1]+1;
            }else{
                val+=2*len[v+1]+1;
                len[v+len[v+1]]=len[v]=len[v+1]+1;
            }
        }
        ans[i]=val;
        RMQ[cnt][0]=Chkmax(i,RMQ[cnt][0]);
    }
    for(LL i=2;i<=(n+1)/2;++i)
        lg[i]=lg[i>>1]+1;
    for(LL j=1;j<=19;++j)
        for(LL i=1;i+(1<<j)-1<=(n+1)/2;++i)
            RMQ[i][j]=Chkmax(RMQ[i][j-1],RMQ[i+(1<<(j-1))][j-1]);
}
inline LL Query(LL l,LL r){
    if(l>(n+1)/2)
        return 0;
    if(r>(n+1)/2)
        r=(n+1)/2;
    LL x=lg[r-l+1];
    return Chkmax(RMQ[l][x],RMQ[r-(1<<x)+1][x]);
}
int main(){
    n=Read(),m=Read();
    for(LL i=1;i<=n;++i)
        a[i]=Read();
    First();
    LL last_ans=0;
    while(m--){
        LL a=Read(),b=Read(),x=Read(),y=Read();
        LL l=(a*last_ans+x-1)%n+1,r=(b*last_ans+y-1)%n+1;
        if(l>r)
            swap(l,r);
        LL now=Query(l,r);
        if(!now){
            printf("-1 -1
");
            printf("%lld %lld %lld
",l,r,last_ans);
            last_ans=1;
        }else{
            printf("%lld %lld
",ans[now],now);
            printf("%lld %lld %lld
",l,r,last_ans);
            last_ans=ans[now]%n*now%n;
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/y2823774827y/p/10147397.html