1 条题解
-
0
Description
给定两个长为 的由 到 组成的字符串 。
有 组互斥对 表示字符 和 无法进行临项交换。
问 是否能通过临项交换变为 。
。
Solution
首先能够发现一个重要的性质:若 为互斥对,则 的相对位置关系固定。
这时就已经有一个 的做法了,枚举每一种数再动态维护是否合法即可,本题时限 秒足以通过。
但这太不优美了。
我们可以考虑从小到大枚举 的每一位,判断 中是否存在字符能够移到相应位置即可。
假设此时枚举到 ,存在两个位置 满足 。由于从小往大枚举,必定有 。
若 能够移动到 ,则 必然能够移动到 ,也就相当于二者是能够互相到达的,所以将 能够移动到 保持不劣。
若是若是 无法移动到 ,则此时将 移动到 明显更优,因为不用经过 。
因此由决策包容性可得:将 移到 要优于将 移到 。
所以对于每一个 中的位置 ,我们可以认为它是由 中最近的对应字符移来的。
这里的最近不是指在原序列中距离最近,而是指在 位置上的数都已经匹配后距离最近的数。
所以上述说法可以转化为:对于 序列中的位置 ,假设它是值 第 次出现的位置,那么 中相对应的位置就也应该是 序列中值 第 次出现的位置。
这也就意味着, 序列中每个数要移到 序列中的位置从一开始就是确定的,不妨设 要移动到 位置,用若干指针扫一遍就能把 预处理出来了。
那么无法移动的情况很明显了:
- 是互斥对。
三维偏序,直接 cdq 就行了。
其中判断是否是互斥对可以用
bitset优化,就不需要 枚举了。总时间复杂度 ,其中 ,明显优于
虽然好像也不是那么明显。Code
#include<bits/stdc++.h> #define INF 1e18 #define K 1005 #define N 100005 using namespace std; struct node{ int v,id; }e[N]; int n,k,m,a[N],b[N],p[N],fl; queue<int>q[K]; bitset<K>c[K],tmp; bool cmp(node x,node y){ return x.v<y.v; } void cdq(int l,int r){ if(l==r) return; int mid=l+r>>1,j=l; cdq(l,mid),cdq(mid+1,r); sort(e+l,e+mid+1,cmp),sort(e+mid+1,e+r+1,cmp); for(int i=mid+1;i<=r;i++){ while(j<=mid&&e[j].v<e[i].v) tmp[e[j].id]=1,j++; if((tmp&c[e[i].id]).count()) fl=0; } for(int i=l;i<=j;i++) tmp[e[i].id]=0; } signed main(){ ios::sync_with_stdio(false); cin>>n>>k>>m,fl=1; for(int i=1,u,v;i<=m;i++){ cin>>u>>v; c[u][v]=1; c[v][u]=1; } for(int i=1;i<=n;i++) cin>>a[i]; for(int i=1;i<=n;i++) cin>>b[i]; for(int i=1;i<=n;i++) cin>>a[i],q[a[i]].push(i); for(int i=1;i<=n;i++){ cin>>b[i],e[i].id=b[i]; if(q[b[i]].empty()){ cout<<"NIE"; return 0; } e[i].v=-q[b[i]].front(); q[b[i]].pop(); } cdq(1,n); if(fl) cout<<"TAK"; else cout<<"NIE"; return 0; }
- 1
信息
- ID
- 5764
- 时间
- 4000ms
- 内存
- 228MiB
- 难度
- 10
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者