有一个(比较显然又有点假的)结论:最优方案中(若存在),每一个数(指$3n$个)最多被移动1次

先$o(n^{2})$枚举移动到队首和队尾的操作次数(即目标状态的一个前缀和后缀),判定能否合法

首先,根据这个前缀和后缀的数字以及个数,可以确定每类数(指$n$类)的操作(但不能确定顺序),即可以知道操作了多少次$L$和$R$

(同时由于不同类的顺序是独立的,这就保证了这个前缀和后缀符合条件,考虑中间未被操作的部分)

其次,对于每一类数,将其$L$和$R$的操作次数组成二元组,分为以下几类:

(1)$(3,0)$和$(0,3)$,一定无解

(2)$(1,1)$,与顺序有关,未被操作数的位置可能是原序列中最左/最右的

(3)$(1,2)$和$(2,1)$,强制顺序(例如$(1,2)$必须先$L$),可以确定未被操作数的位置

(4)除此之外($(0,0)$、$(0,1)$和$(1,0)$),顺序无关(一共就1次)且可以确定未被操作数的位置

最后,考虑中间这些未被操作数的位置关系:

假设已经确定了未被操作数的位置(在目标状态中的),我们不需要算出具体的初始位置,比较相邻两数的对应位置是否满足单调性(因为未被操作的两数相对顺序不变)、操作的顺序是否有矛盾

(对应位置:根据目标状态以及二元组可以判断其在初始状态中是该类数中的第几个,初始状态中该类数的第“几”个即对应位置)

操作顺序的限制分为两类:1.对于第(2)(3)种情况,同一类数不同操作的限制;2.对于不同类数的同一种操作,距离1或$3n$越远的越优先,可以证明存在矛盾等价于存在4元环(点更多可以压缩)

还有$(1,1)$的情况,考虑2-sat连边,限制(边)同样有两类,每一类再分为确定点与非确定点、非确定点与非确定点两类讨论一下即可

判定时间复杂度为$o(n^{2})$,因此总复杂度为$o(n^{4})$,可以通过

  1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 105
4 struct ji{
5 int nex,to;
6 }edge[N*N];
7 vector<int>vv,v[N];
8 int E,n,x,ans,a[N],mx[N],mn[N],sl[N],sr[N],s[N],p[N],head[N],vis[N];
9 void add(int x,int y){
10 edge[E].nex=head[x];
11 edge[E].to=y;
12 head[x]=E++;
13 }
14 void dfs(int k){
15 if (vis[k])return;
16 vis[k]=1;
17 for(int i=head[k];i!=-1;i=edge[i].nex)dfs(edge[i].to);
18 }
19 bool pd(int k){
20 memset(vis,0,sizeof(vis));
21 dfs(k);
22 return vis[k^1];
23 }
24 bool pd(int x,int y){
25 memset(sl,0,sizeof(sl));
26 memset(sr,0,sizeof(sr));
27 for(int i=1;i<=x;i++)sl[a[i]]++;
28 for(int i=y;i<=3*n;i++)sr[a[i]]++;
29 for(int i=1;i<=n;i++)
30 if ((sl[i]==3)||(sr[i]==3))return 0;
31 vv.clear();
32 memset(s,0,sizeof(s));
33 memset(p,0,sizeof(p));
34 p[x]=-1,p[y]=0x3f3f3f3f;
35 for(int i=x+1;i<y;i++){
36 if ((sl[a[i]]==1)&&(sr[a[i]]==1)){
37 vv.push_back(i);
38 continue;
39 }
40 if (!s[a[i]]){
41 p[i]=0;
42 if ((sl[a[i]]==2)&&(sr[a[i]]==0))p[i]=2;
43 }
44 if (s[a[i]]==1){
45 p[i]=2;
46 if ((!sl[a[i]])&&(!sr[a[i]]))p[i]=1;
47 }
48 if (s[a[i]]==2)p[i]=2;
49 p[i]=v[a[i]][p[i]];
50 if (p[i]<p[i-1])return 0;
51 s[a[i]]++;
52 }
53 for(int i=1;i<=n;i++)
54 if ((sl[i]==2)&&(sr[i]==1))
55 for(int j=1;j<=n;j++)
56 if ((sl[j]==1)&&(sr[j]==2)&&(mx[j]<mx[i])&&(mn[j]<mn[i]))return 0;
57 E=0;
58 memset(head,-1,sizeof(head));
59 for(int i=0;i<vv.size();i++){
60 if (p[vv[i]-1]){
61 if (v[a[vv[i]]][2]<p[vv[i]-1])return 0;
62 if (v[a[vv[i]]][0]<p[vv[i]-1])add(2*i,2*i+1);
63 }
64 else{
65 if (v[a[vv[i]]][2]<v[a[vv[i]-1]][0])return 0;
66 if (v[a[vv[i]]][2]<v[a[vv[i]-1]][2])add(2*i+1,2*i-2);
67 if (v[a[vv[i]]][0]<v[a[vv[i]-1]][0])add(2*i,2*i+1);
68 else
69 if (v[a[vv[i]]][0]<v[a[vv[i]-1]][2])add(2*i,2*i-2);
70 }
71 if (p[vv[i]+1]){
72 if (v[a[vv[i]]][0]>p[vv[i]+1])return 0;
73 if (v[a[vv[i]]][2]>p[vv[i]+1])add(2*i+1,2*i);
74 }
75 else{
76 if (v[a[vv[i]]][0]>v[a[vv[i]+1]][2])return 0;
77 if (v[a[vv[i]]][0]>v[a[vv[i]+1]][0])add(2*i,2*i+3);
78 if (v[a[vv[i]]][2]>v[a[vv[i]+1]][2])add(2*i+1,2*i);
79 else
80 if (v[a[vv[i]]][2]>v[a[vv[i]+1]][0])add(2*i+1,2*i+3);
81 }
82 }
83 for(int i=1;i<=n;i++)
84 if ((sl[i]==2)&&(sr[i]==1))
85 for(int j=0;j<vv.size();j++)
86 if ((mx[a[vv[j]]]<mx[i])&&(mn[a[vv[j]]]<mn[i]))add(2*j+1,2*j);
87 for(int i=1;i<=n;i++)
88 if ((sl[i]==1)&&(sr[i]==2))
89 for(int j=0;j<vv.size();j++)
90 if ((mx[a[vv[j]]]>mx[i])&&(mn[a[vv[j]]]>mn[i]))add(2*j,2*j+1);
91 for(int i=0;i<vv.size();i++)
92 for(int j=0;j<vv.size();j++)
93 if ((i!=j)&&(mx[a[vv[j]]]<mx[a[vv[i]]])&&(mn[a[vv[j]]]<mn[a[vv[i]]])){
94 add(2*i,2*j);
95 add(2*j+1,2*i+1);
96 }
97 for(int i=0;i<vv.size();i++)
98 if ((pd(2*i))&&(pd(2*i+1)))return 0;
99 return 1;
100 }
101 int main(){
102 scanf("%d",&n);
103 for(int i=1;i<=3*n;i++){
104 scanf("%d",&x);
105 v[x].push_back(i);
106 }
107 for(int i=1;i<=3*n;i++){
108 scanf("%d",&a[i]);
109 if (!mn[a[i]])mn[a[i]]=i;
110 mx[a[i]]=i;
111 }
112 ans=0x3f3f3f3f;
113 for(int i=0;i<=3*n;i++)//[1,i]
114 for(int j=3*n+1;j>i;j--)//[j,3*n]
115 if ((i+3*n-j+1<ans)&&(pd(i,j)))ans=i+3*n-j+1;
116 if (ans==0x3f3f3f3f)ans=-1;
117 printf("%d",ans);
118 }

最新文章

  1. Android屏幕适配总结
  2. quick cocos2d-x 入门---井字棋
  3. 更改win7开机界面
  4. jmeter之调度器配置
  5. android activity 跳转传值问题研究
  6. OD: Heap Exploit : DWORD Shooting &amp; Opcode Injecting
  7. DOS命令行 定时关机&amp;取消定时关机
  8. C++学习之嵌套类和局部类
  9. gzip: File too large错误
  10. UWP 五星好评
  11. 通讯协议序列化解读(一) Protobuf详解教程
  12. Python编程从入门到实践笔记——文件
  13. 2019.03.28 bzoj3326: [Scoi2013]数数(数位dp)
  14. 2019浙大校赛--G--Postman(简单思维题)
  15. 今日头条面试题——LRU原理和Redis实现
  16. yii2 basic版本的一些配置
  17. 「Django」浏览+1的操作
  18. Java 持久化之 -- IO 全面整理(看了绝不后悔)
  19. BZOJ3203 SDOI2013保护出题人(三分)
  20. spring---transaction(6)---事务的配置

热门文章

  1. 微软发布了Visual Studio 2022 RC版,并将在11月8日发布正式版
  2. 教你轻松构建基于 Serverless 架构的小程序
  3. Lamport时间戳论文笔记
  4. ReentrantLock可重入锁、公平锁非公平锁区别与实现原理
  5. Java 读取PDF中的表格
  6. Java继承、重写与重载
  7. WEB安全指南
  8. 【UE4 C++ 基础知识】&lt;15&gt; 智能指针 TSharedPtr、UniquePtr、TWeakPtr、TSharedRef
  9. spring、spring boot中配置多数据源
  10. numpy读取本地数据和索引