多校第4场1012

理解题意以后会发现时比较简单的线段树,理解题意以后首先应该想到一个贪心,就是再寻找最终答案的第i个数时,饿哦们要尽量使这个数尽可能大。那么我们找[1,pos[i]+1]这个区间中已经组队的位置的最大值,记为l,然后找[l+1pos[i]+1]之间未被找过的最大的数。(这里组队的意思是可以详见程序,并不是被找过了)。然后注意一下细节,是一个比较好维护的线段树,复杂付就是线段树的复杂度o(nlogn)。

题解上写维护组队的右端点是用set维护的,比赛当时也想到了用set维护,但是后来感觉好像只需要把PushUp和Modify稍加修改就好了,但是改了一下,感觉有点烦,索性就复制,粘贴,多谢了2个函数(几乎一样的)。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define FOR(i,x,y)  for(int i = x;i < y;i ++)
#define IFOR(i,x,y) for(int i = x;i > y;i --)
#define ll long long
#define lrt rt<<1
#define rrt rt<<1|1
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define N 100010

using namespace std;

int pos[N],num[N],ans[N],n;
bool vis[N];

struct Tree{
    int l,r;
    int maxx,en_maxx;
}tree[N<<2];

void PushUp(int rt){
    tree[rt].maxx = max(tree[lrt].maxx,tree[rrt].maxx);
}

void Build(int rt,int l,int r){
    tree[rt].l = l; tree[rt].r = r; tree[rt].maxx = -1,tree[rt].en_maxx = 0;
    if(l == r){
        tree[rt].maxx = num[l];
        return;
    }
    int mid = (l+r)>>1;
    Build(lson);
    Build(rson);
    PushUp(rt);
}

void Modify(int rt,int k){
    if(tree[rt].l == tree[rt].r){
        tree[rt].maxx = -1;
        return;
    }
    int mid = (tree[rt].l+tree[rt].r)>>1;
    if(k <= mid) Modify(lrt,k);
    else Modify(rrt,k);
    PushUp(rt);
}

int Query(int rt,int l,int r){
    if(tree[rt].l == l && tree[rt].r == r)    return tree[rt].maxx;
    int mid = (tree[rt].l + tree[rt].r)>>1;
    if(r <= mid) return Query(lrt,l,r);
    else if(l > mid)    return Query(rrt,l,r);
    else{
        return max(Query(lson),Query(rson));
    }
}

int Query_en(int rt,int l,int r){
    if(tree[rt].l == l && tree[rt].r == r)  return tree[rt].en_maxx;
    int mid = (tree[rt].l + tree[rt].r)>>1;
    if(r <= mid) return Query_en(lrt,l,r);
    else if(l > mid)    return Query_en(rrt,l,r);
    else{
        return max(Query_en(lson),Query_en(rson));
    }
}

void PushUp_en(int rt){
    tree[rt].en_maxx = max(tree[lrt].en_maxx,tree[rrt].en_maxx);
}

void Modify_en(int rt,int k){
    if(tree[rt].l == tree[rt].r){
        tree[rt].en_maxx = tree[rt].l;
        return;
    }
    int mid = (tree[rt].l+tree[rt].r)>>1;
    if(k <= mid) Modify_en(lrt,k);
    else Modify_en(rrt,k);
    PushUp_en(rt);
}

int main()
{
    //freopen("test.in","r",stdin);
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        FOR(i,1,n+1){
            scanf("%d",&num[i]);
            pos[num[i]] = i;
            ans[i] = -1;
            vis[i] = false;
        }
        Build(1,1,n);
        FOR(i,1,n+1){
            if(ans[i] != -1) continue;
            int r = pos[i];
            int l = Query_en(1,1,r)+1;
            //if(i == 2)
               // printf("hahah
");
            if(l > r)   ans[i] = ans[i+1];
            else{
                int tem = Query(1,l,r);
                if(r == n)  ans[i] = tem;
                else{
                    if(!vis[num[pos[i]+1]]){
                        ans[i] = max(tem,num[pos[i]+1]);
                    }
                    else ans[i] = tem;
                }
            }
            vis[ans[i]] = true;
            Modify(1,pos[ans[i]]);
            if(pos[ans[i]] <= pos[i])
                Modify_en(1,pos[i]);
            if(pos[ans[i]] < pos[i]){
                FOR(j,pos[ans[i]],pos[i]){
                    ans[num[j]] = num[j+1];
                    vis[ans[num[j]]] = true;
                    Modify(1,pos[ans[num[j]]]);
                }
            }
        }
        printf("%d",ans[1]);
        FOR(i,2,n+1){
            printf(" %d",ans[i]);
        }
        printf("
");
    }
    return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

原文地址:https://www.cnblogs.com/hqwhqwhq/p/4811900.html