D. Balanced Playlist

D. Balanced Playlist
思路:
第一种情况:先找出最大值 再找出最小值,要是最大值 小于等于最小值的2倍(maxn<=2minn)所有元素都可以无限循环下去 输出-1.
第二中情况:我们可用线段树 ,线段树有三个值 maxn(区间最大值) minn(区间最小值) ok(此区间是否合法);
要判断此区间是否合法 先判断右子树的最小值的2倍是否大于等于左子树 即(tree[2
node+1].minn2>=tree[2node].maxn)是的话ok=1,
否ok=0。
然后枚举1到n 在二分查询是否合法 即(I 到 I+m 的区间是否合法)要是合法l=m+1 否则r=m;
难点: 线段树 回溯的时候要注意 当ok=0的时候就不用在判断了 否则在判断右子树的ok 要是都不等于在判断最大值与最小值。
在查询的时候 l 到 r 每次查询的节点在进行判断是否合法 然后再将查询的节点ok的值相乘 就可以了
代码

#include<bits/stdc++.h>
using namespace std;
const int N=3e5+7;
struct node{
    int minn,maxn,ok;
}tree[4*N];

int last_max=0,n,a[N],maxn,minn=INT_MAX;

#define lson 2*node
#define rson 2*node+1
#define m (l+r)/2

void push_down(int node){
    tree[node].maxn=max(tree[lson].maxn,tree[rson].maxn);
    tree[node].minn=min(tree[lson].minn,tree[rson].minn);
    if(tree[lson].ok==0){
        tree[node].ok=0;
    }else if(tree[rson].ok==0){
        tree[node].ok=0;
    }else if(tree[lson].maxn>2*tree[rson].minn){
        tree[node].ok=0;
    }else{
        tree[node].ok=1;
    }
}

void update(int v,int pos,int l,int r,int node){
    if(l==r){
        tree[node].maxn=tree[node].minn=v;
        tree[node].ok=1;
        return;
    }
    if(pos<=m)update(v,pos,l,m,lson);
    else update(v,pos,m+1,r,rson);
    push_down(node);
}

bool  query(int ql,int qr,int l,int r,int node){
    if(ql<=l&&qr>=r){
        int f=0;
        if(last_max==0){
            f=tree[node].ok;
        }else if(tree[node].ok==0){
            f=0;
        }else if(tree[node].minn*2>=last_max){
            f=1;
        }else if(tree[node].minn*2<last_max){
            f=0;
        }
        last_max=max(last_max,tree[node].maxn);
        return f;
    }
    int ans=1;
    if(ql<=m)ans*=query(ql,qr,l,m,lson);
    if(qr>m)ans*=query(ql,qr,m+1,r,rson);
    return ans;
}


int main(){
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d",&a[i]);
        maxn=max(maxn,a[i]);
        minn=min(minn,a[i]);
    }
    if(maxn<=2*minn){
        for(int i=1;i<=n;i++)printf("-1 ");
    }else{
        for(int i=0;i<3*n;i++){
            update(a[i%n],i+1,1,3*n,1);
        }
        for(int i=1;i<=n;i++){
            int l=1,r=2*n-1;
            while(l<r){
                last_max=0;
                if(query(i,i+m,1,3*n,1))l=m+1;
                else r=m;
            }
            printf("%d ",l);
        }
    }
}
发布了10 篇原创文章 · 获赞 1 · 访问量 187

猜你喜欢

转载自blog.csdn.net/weixin_45676038/article/details/102673182