A1,A2 - Prefix Flip
首先可以发现由a变到0,需要最多n次,方法如下:
对于第i位(i<a.length()-1),如果a[i] != a[i+1],对于a[0]到a[i]执行操作。
然后b到0,也最多n次。把a到0的操作+0到b的操作就是答案。
/*
AuThOr Gwj
*/
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define KEEP while(1)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define debug_pair(A) cerr<<A.FIR<<" "<<A.SEC<<endl;
#define biggest(A,B) A=max(A,B)
#define smallest(A,B) A=min(A,B)
#define get(a) cin>>a
#define get2(a,b) cin>>a>>b
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
typedef pair<mp,mp> superpair;
vector<int> work(string s){
vector<int> res;
rep(i,s.length()){
if(i!=s.length()-1&&s[i]!=s[i+1]){
res.PB(i+1);
}
}
if(s[s.length()-1]=='0'){
}
else{
res.PB(s.length());
}
return res;
}
void solve(){
int n;
cin>>n;
string s1,s2;
cin>>s1>>s2;
vector<int> res,res2;
res=work(s1);
res2=work(s2);
reverse(ALL(res2));
cout<<res.size()+res2.size()<<" ";
for(auto it:res) cout<<it<<" ";for(auto it:res2) cout<<it<<" ";cout<<endl;
}
int main(){
fastio;
int t;
cin>>t;
while(t--) solve();
return 0;
}
B - Unmerge
可以发现merge操作时在一个空串中连续加入几个段
[
l
1
,
r
1
]
,
[
l
2
,
r
2
]
,
[
l
3
,
r
3
]
.
.
.
[
l
k
,
r
k
]
[l_1,r_1],[l_2,r_2],[l_3,r_3]...[l_k,r_k]
[l1,r1],[l2,r2],[l3,r3]...[lk,rk]其中
[
l
i
,
r
i
]
[l_i,r_i]
[li,ri]来自a那么(
i
M
O
D
2
=
=
1
iMOD2==1
iMOD2==1),否则来自b。
然后由于第一段走完了第二段才走,所以
a
l
2
>
m
a
x
{
a
l
1
.
.
.
r
1
}
a_{l_2}>max\{a_{l_1...r_1}\}
al2>max{al1...r1},同理
a
l
3
>
m
a
x
{
a
l
2
.
.
.
r
2
}
⇒
a
l
3
>
a
l
2
>
m
a
x
{
a
1
.
.
.
a
r
2
}
a_{l_3}>max\{a_{l_2...r_2}\} \Rightarrow a_{l_3}>a_{l_2}>max\{a_1...a_{r_2}\}
al3>max{al2...r2}⇒al3>al2>max{a1...ar2}。
所以
l
i
l_i
li必须满足
a
l
i
a_{l_i}
ali是
a
1
.
.
.
a
l
i
−
1
a_1...a_{l_i-1}
a1...ali−1中最大的一个,这样我们就可以发现
l
i
l_i
li的可能位置。然后就有了这些段。
d
p
i
,
j
dp_{i,j}
dpi,j表示考虑前i个段总长度=j,是否可能。
d
p
i
,
j
=
d
p
i
−
1
,
j
∣
d
p
i
−
1
,
j
−
l
i
dp_{i,j}=dp_{i-1,j}|dp_{i-1,j-l_i}
dpi,j=dpi−1,j∣dpi−1,j−li
/*
AuThOr Gwj
*/
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define KEEP while(1)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define debug_pair(A) cerr<<A.FIR<<" "<<A.SEC<<endl;
#define biggest(A,B) A=max(A,B)
#define smallest(A,B) A=min(A,B)
#define get(a) cin>>a
#define get2(a,b) cin>>a>>b
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
typedef pair<mp,mp> superpair;
bool dp[4004][2002];
int a[4004];
void solve(){
memset(dp,0,sizeof(dp));
int n;
cin>>n;
n<<=1;
rb(i,1,n){
cin>>a[i];
}
vector<int> v;
dp[0][0]=1;
int st=1;
int maxi=a[1];
rb(i,2,n){
if(a[i]>maxi){
v.PB(i-st);
st=i;
}
maxi=max(a[i],maxi);
}
v.PB(n-st+1);
rb(i,1,v.size()){
rb(j,0,n/2){
dp[i][j]|=(j>=v[i-1]? dp[i-1][j-v[i-1]]:0)|dp[i-1][j];
}
}
if(dp[v.size()][n/2]){
cout<<"YES"<<endl;
}
else{
cout<<"NO"<<endl;
}
}
int main(){
fastio;
int t;
cin>>t;
while(t--){
solve();
}
return 0;
}
C - Mastermind
定义
p
i
c
k
=
y
−
x
pick=y-x
pick=y−x,显然就是要从数组中取出
p
i
c
k
pick
pick个数交换位置,使得每一个位置的数与原来不同,其余的选n-y个把颜色换成没出现的颜色。特殊的:
p
i
c
k
=
m
i
n
(
2
,
n
−
x
)
pick=min(2,n-x)
pick=min(2,n−x);如果只有两种颜色,
p
i
c
k
pick
pick为最小的偶数大于等于
y
−
x
y-x
y−x的偶数。
假设选出来的数位
{
a
1
.
.
.
a
p
i
c
k
}
\{a_1...a_{pick}\}
{a1...apick},显然如果最多的数
>
⌊
n
2
⌋
>\lfloor \frac{n}{2} \rfloor
>⌊2n⌋则肯定不满足。否则将a数组按照个数的多少降序排序(相同的数排在一起),将第一种颜色的第一个连向第二种颜色的第一个,第一种颜色的第二个连向第二种颜色的第二个…
code:
/*
AuThOr Gwj
*/
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define KEEP while(1)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define debug_pair(A) cerr<<A.FIR<<" "<<A.SEC<<endl;
#define biggest(A,B) A=max(A,B)
#define smallest(A,B) A=min(A,B)
#define get(a) cin>>a
#define get2(a,b) cin>>a>>b
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
typedef pair<mp,mp> superpair;
int n,x,y;
int cnt[100000+20],al[100000+20],a[100000+20],res[100000+20];
bool cmp(int A,int B){
if(al[a[A]]!=al[a[B]])
return al[a[A]]>al[a[B]];
return a[A]<a[B];
}
int find_(int l,int r){
if(l==1) l++;
int kk=0;
rb(i,1,n+1){
if(cnt[i]){
kk++;
}
}
if(kk==2){
if(l&1){
l++;
}
}
return min(r,l);
}
void solve(){
get(n);
get2(x,y);
memset(cnt,0,sizeof(cnt));
memset(al,0,sizeof(al));
memset(res,0,sizeof(res));
rb(i,1,n){
get(a[i]);
cnt[a[i]]++;
}
int pick=y-x;
vector<int> pos;
int ok=0;
int f=find_(pick,n-x);
ok=f-pick;
pick=f;
rb(i,1,n){
if((al[a[i]]+1)*2>pick||pos.size()==pick){
if(x){
x--;
res[i]=a[i];
}
}
else{
al[a[i]]++;
pos.PB(i);
}
}
if(pos.size()<pick){
cout<<"NO"<<endl;
return ;
}
cout<<"YES"<<endl;
sort(ALL(pos),cmp);
int zhi;
rep(i,pos.size()){
if(a[pos[i]]!=a[pos[0]]){
zhi=i;
break;
}
}
rep(i,pos.size()){
res[pos[zhi]]=a[pos[i]];
zhi++;
zhi%=pos.size();
}
int tmp;
rb(i,1,n+1){
if(!cnt[i]) tmp=i;
}
rb(i,1,n){
if(!res[i])
res[i]=tmp;
else
if(ok&&res[i]!=a[i]){
ok--;
res[i]=tmp;
}
}
rb(i,1,n) cout<<res[i]<<" ";cout<<endl;
}
int main(){
fastio;
int t;
cin>>t;
while(t--) solve();
return 0;
}