题目链接: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; }