Educational Codeforces Round 37 (Rated for Div. 2)C. Swap Adjacent Elements

题目链接:C. Swap Adjacent Elements

题意:给你一个1~n的序列,然后一个n-1长的01串,为一代表可以和后面一个位置的数交换。问你能否通过交换是序列从小到大;

题解:统计每个数字的位置p[i],我们想要一个数字现能够回到原来的位置i必须max(i,p[i])-1到min(i,p[i])全部为一。我们用线段树或者前缀和。

就可以快速判断一段是否全部为一(我用的是线段树),对于每一个不在原来位置上的数判断一次就好了,

#include<bits/stdc++.h>
#include<set>
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#define pb push_back
#define ll long long
#define PI 3.14159265
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define eps 1e-7
typedef unsigned long long ull;
const int mod=1e9+7;
const int maxn=2e5+5;
const int root=1e8;
using namespace std;
ll n,k;
int t,a[maxn];
int p[maxn];
string s;
int tree[maxn<<2];
void push(int rt)
{
    if(tree[rt<<1]&&tree[rt<<1|1])tree[rt]=1;
    else tree[rt]=0;return;
}
void built(int l,int r,int rt)
{
    if(l==r)
    {
        if(s[l-1]=='1')tree[rt]=1;
        else tree[rt]=0;
        return ;
    }
    int m=(l+r)/2;
    built(ls);
    built(rs);
    push(rt);
}
bool query(int L,int R,int l,int r,int rt)
{
    if(l>R||r<L)return 1;
    if(L<=l&&r<=R)
    {
        return tree[rt];
    }
    int m=(l+r)/2;
    return query(L,R,ls)&&query(L,R,rs);
}
int main()
{
    std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];p[a[i]]=i;
    }
    cin>>s;
    built(1,n-1,1);
    for(int i=1;i<n;i++)
    {
        int l,r;
        if(i!=p[i])
        {
            l=min(i,p[i]);r=max(i,p[i]);
            if(!query(l,r-1,1,n-1,1))
            {
                cout<<"NO"<<endl;return 0;
            }
        }
    }
    cout<<"YES"<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/lhclqslove/p/8412500.html