ICode9

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

线段树求后继+环——cf1237D

2019-10-23 18:04:14  阅读:237  来源: 互联网

标签:rt int 线段 树求 ans cf1237D pos2 rson pos1


/*
首先开三倍消环(两倍是不够的),倒序求值,线段树找一下后继即可 
*/
#include<bits/stdc++.h>
using namespace std;
#define N 300005

int n,a[N],ans[N];

#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int Max[N<<2],Min[N<<2],pos1,pos2;
void build(int l,int r,int rt){
    Max[rt]=0;Min[rt]=1e9+7;
    if(l==r){
        Max[rt]=Min[rt]=a[l];
        return;
    }
    int m=l+r>>1;
    build(lson);build(rson);
    Max[rt]=max(Max[rt<<1],Max[rt<<1|1]);
    Min[rt]=min(Min[rt<<1],Min[rt<<1|1]);
}
void query1(int L,int R,int v,int l,int r,int rt){//找第一个比v大的后继
    if(l==r){
        if(Max[rt]>v)pos1=min(pos1,l);
        return;
    } 
    int m=l+r>>1;
    if(L<=l && R>=r){//可以在区间里二分了 
        if(Max[rt<<1]>v)
            query1(L,R,v,lson);
        else if(Max[rt<<1|1]>v)
            query1(L,R,v,rson);
        return;
    }
    if(L<=m)query1(L,R,v,lson);
    if(R>m)query1(L,R,v,rson); 
}
void query2(int L,int R,double v,int l,int r,int rt){//找第一个比v小的后继 
    if(l==r){
        if(Min[rt]<v)pos2=min(pos2,l);
        return;
    }
    int m=l+r>>1;
    if(L<=l && R>=r){
        if(Min[rt<<1]<v)
            query2(L,R,v,lson);
        else if(Min[rt<<1|1]<v)
            query2(L,R,v,rson);
        return;
    }
    if(L<=m)query2(L,R,v,lson);
    if(R>m)query2(L,R,v,rson);
} 

int main(){
    cin>>n;
    int mx=0,mi=0x3f3f3f3f;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        a[i+n]=a[i+2*n]=a[i];
        mx=max(mx,a[i]);
        mi=min(mi,a[i]);
    }
    
    if(mx<=mi*2){
        for(int i=1;i<=n;i++)cout<<-1<<" ";
        return 0;
    }
    
    build(1,3*n,1);
    ans[3*n]=1;
    for(int i=3*n-1;i>=1;i--){
        pos1=pos2=3*n+1;
        query1(i+1,2*n,a[i],1,3*n,1);//找第一个大于a[i]的位置
        query2(i+1,3*n,1.0*a[i]/2,1,3*n,1);//找第一个小于a[i]/2的位置 
        if(pos1==3*n+1 && pos2==3*n+1)//后面都可行 
            ans[i]=3*n-i+1; 
        else if(pos1==3*n+1)//后面没有比a[i]大的 
            ans[i]=pos2-i; 
        else if(pos2==3*n+1)//后面没有比a[i]/2小的 
            ans[i]=ans[pos1]+pos1-i;
        else if(pos1<pos2)//大的在小的前面
            ans[i]=ans[pos1]+pos1-i;
        else if(pos1>pos2)
            ans[i]=pos2-i; 
    }
    for(int i=1;i<=n;i++)
        cout<<ans[i]<<" ";
} 

 

标签:rt,int,线段,树求,ans,cf1237D,pos2,rson,pos1
来源: https://www.cnblogs.com/zsben991126/p/11727773.html

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

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

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

ICode9版权所有