Codeforces1187 D. Subarray Sorting(思维,线段树)

题意:

在这里插入图片描述

解法:
首先判断a[]和b[]的元素是否相同,不相同则一定无解.

考虑按b[1],b[2],b[3]的顺序依次恢复数组,
对于b[1],找到a[]中b[1]出现的最左位置pos,
如果min{a[1,pos]}=b[1],那么可以将a[pos]移动过来,然后我们将a[pos]删掉.

依次判断过去即可,区间min操作和删除操作用线段树维护即可.

算法总复杂度O(n*log).
code:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxm=3e5+5;
queue<int>pos[maxm];
int a[maxm];
int b[maxm];
int n;
struct Tree{
    int mi[maxm<<2];
    inline void pp(int node){
        mi[node]=min(mi[node*2],mi[node*2+1]);
    }
    void update(int x,int val,int l,int r,int node){
        if(l==r){
            mi[node]=val;return ;
        }
        int mid=(l+r)/2;
        if(x<=mid)update(x,val,l,mid,node*2);
        else update(x,val,mid+1,r,node*2+1);
        pp(node);
    }
    int ask(int st,int ed,int l,int r,int node){
        if(st<=l&&ed>=r)return mi[node];
        int mid=(l+r)/2;
        int ans=1e9;
        if(st<=mid)ans=min(ans,ask(st,ed,l,mid,node*2));
        if(ed>mid)ans=min(ans,ask(st,ed,mid+1,r,node*2+1));
        return ans;
    }
    void build(int l,int r,int node){
        if(l==r){
            mi[node]=a[l];
            return ;
        }
        int mid=(l+r)/2;
        build(l,mid,node*2);
        build(mid+1,r,node*2+1);
        pp(node);
    }
}T;
void solve(){
    cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i];
    for(int i=1;i<=n;i++)cin>>b[i];
    //判断元素是否相同
    map<int,int>mp;
    for(int i=1;i<=n;i++){
        mp[a[i]]++;mp[b[i]]--;
    }
    for(auto i:mp){
        if(i.second!=0){
            cout<<"NO"<<endl;
            return ;
        }
    }
    //切记初始化
    for(int i=1;i<=n;i++){
        while(pos[a[i]].size())pos[a[i]].pop();
    }
    //
    for(int i=1;i<=n;i++){
        pos[a[i]].push(i);
    }
    T.build(1,n,1);
    for(int i=1;i<=n;i++){
        int id=pos[b[i]].front();pos[b[i]].pop();
        int mi=T.ask(1,id,1,n,1);
        if(mi!=b[i]){
            cout<<"NO"<<endl;
            return ;
        }
        T.update(id,1e9,1,n,1);
    }
    cout<<"YES"<<endl;
}
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);
    int T;cin>>T;while(T--)
    solve();
    return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值