「题解」Codeforces 1572B Xor of 3
我知道你很急,但你先别急。
我急了我急了我急了。
如果直接上去莽构造的话,很可能就是像我一样大分讨的后果。
先特判掉全是 1,或者 1 的个数是奇数的情况。
我的做法是考虑所有极长连续 1 段,然后尝试分类讨论,构造。
如果是一个偶数段可以直接消掉自己。如果是相邻两个奇数段,中间隔了奇数个 0 可以直接消掉,如果中间隔了偶数个 0,需要从一端的旁边借一个 0 的位才能消掉。
问题就是两个奇数段中间隔了奇数个 0,如果这两个奇数段一个在开头一个在结尾就没办法借 0 了。
所以需要想办法从前往后消段的时候,尝试用一个偶数段把第一个奇数段给操作成一个开头不在最边上的奇数段。
还有就是为了避免操作数 \(>n\),每来一个偶数段先尝试能不能和前面奇数段一起消,如果前面奇数段已经消没了的话才自己一个人消。
最后如果真的只剩下一个开头一个结尾俩段,就无解了。
连拍带写带分讨写了一个小时/乐
更好写更简单的做法是,考虑如果 \(n\) 是奇数,那么先将 \(n-2,n-4,...,1\) 操作,这样 \(1\) 位置就是整个序列的异或和,为 0,并且 \(a_{2k}=a_{2k+1}\),所以再操作一遍 \(1,3,5\cdots,n-2\) 即可。
如果 \(n\) 是偶数,找到一个长度为奇数的前缀使得其异或和为 \(0\),然后劈开,左右两部分依然按照上面那个奇数来做。
如果找不到这样的前缀,容易证明无论怎么操作,所有长度为奇数的前缀异或和都不为 \(0\),故无解。
第一种做法代码:
#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<ctime>
#include<random>
#include<assert.h>
#define pb emplace_back
#define mp make_pair
#define fi first
#define se second
#define dbg(x) cerr<<"In Line "<< __LINE__<<" the "<<#x<<" = "<<x<<'\n'
#define dpi(x,y) cerr<<"In Line "<<__LINE__<<" the "<<#x<<" = "<<x<<" ; "<<"the "<<#y<<" = "<<y<<'\n'
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int>pii;
typedef pair<ll,int>pli;
typedef pair<ll,ll>pll;
typedef pair<int,ll>pil;
typedef vector<int>vi;
typedef vector<ll>vll;
typedef vector<pii>vpii;
typedef vector<pil>vpil;
template<typename T>T cmax(T &x, T y){return x=x>y?x:y;}
template<typename T>T cmin(T &x, T y){return x=x<y?x:y;}
template<typename T>
T &read(T &r){
r=0;bool w=0;char ch=getchar();
while(ch<'0'||ch>'9')w=ch=='-'?1:0,ch=getchar();
while(ch>='0'&&ch<='9')r=r*10+(ch^48),ch=getchar();
return r=w?-r:r;
}
template<typename T1,typename... T2>
void read(T1 &x,T2& ...y){read(x);read(y...);}
const int mod=998244353;
inline void cadd(int &x,int y){x=(x+y>=mod)?(x+y-mod):(x+y);}
inline void cdel(int &x,int y){x=(x-y<0)?(x-y+mod):(x-y);}
inline int add(int x,int y){return (x+y>=mod)?(x+y-mod):(x+y);}
inline int del(int x,int y){return (x-y<0)?(x-y+mod):(x-y);}
int qpow(int x,int y){
int s=1;
while(y){
if(y&1)s=1ll*s*x%mod;
x=1ll*x*x%mod;
y>>=1;
}
return s;
}
#define Win do{puts("YES");return ;}while(0)
#define Lose do{puts("NO");return ;}while(0)
#define Alice do{puts("Alice");return ;}while(0)
#define Bob do{puts("Bob");return ;}while(0)
#define Line cerr << "----------\n"
const int N=200010;
int n;
int a[N];
vi outvec;
int pt(pii x){
return (x.se-x.fi+1)&1;
}
void qwe(int x){
assert(x<=n-2);
int z=a[x]^a[x+1]^a[x+2];
a[x]=a[x+1]=a[x+2]=z;
outvec.pb(x);
}
void solve(){
read(n);int s=0;vi().swap(outvec);
int mn=1;
for(int i=1;i<=n;i++)read(a[i]),s^=a[i],cmin(mn,a[i]);
if(s)Lose;
if(mn==1)Lose;
vpii vec;
for(int l=1,r;l<=n;l=r+1){
r=l;
if(a[l]){
while(r<n&&a[r+1])++r;
vec.pb(mp(l,r));
int len=vec.size();
#define z vec[len-1]
#define y vec[len-2]
#define x vec[len-3]
if(pt(z)==0){
if(len>=2 && (z.fi&1)==(y.fi&1)){
for(int i=y.se;i<z.fi-2;i+=2)qwe(i);
qwe(z.fi-2);
for(int i=z.fi;i<z.se-1;i+=2)qwe(i);
for(int i=z.fi-4;i>=y.fi;i-=2)qwe(i);
vec.pop_back();
vec.pop_back();
vec.push_back(mp(z.se,z.se));
}
else if(len>=2){
for(int i=z.fi-2;i>=y.se+1;i-=2)qwe(i);
int L=y.fi,R=z.se;
vec.pop_back();
vec.pop_back();
vec.push_back(mp(L,R));
}
else{
if(z.se!=n)
for(int i=z.se-1;i>=z.fi;i-=2)
qwe(i);
else
for(int i=z.fi-1;i<z.se;i+=2)qwe(i);
vec.pop_back();
}
}
else{
if(len>=2){
if((z.fi&1) == (y.fi&1)){
for(int i=y.se;i<=z.fi-2;i+=2)
qwe(i);
for(int i=z.fi;i<z.se;i+=2)qwe(i);
for(int i=z.fi-4;i>=y.fi;i-=2)qwe(i);
vec.pop_back();
vec.pop_back();
}
else{
if(y.fi!=1){
for(int i=y.se;i<z.fi-1;i+=2)qwe(i);
for(int i=y.fi-1;i<z.se;i+=2)qwe(i);
vec.pop_back();
vec.pop_back();
}
else if(z.se!=n){
for(int i=y.se;i<z.fi-1;i+=2)qwe(i);
for(int i=z.se-1;i>=y.fi;i-=2)qwe(i);
vec.pop_back();
vec.pop_back();
}
}
}
}
#undef x
#undef y
#undef z
}
}
int len=vec.size();
if(len){
// assert(0);
Lose;
}
else{
puts("YES");
cout << outvec.size() << '\n';
for(auto i:outvec)cout << i << ' ';
if(outvec.size())puts("");
assert((int)outvec.size()<=n);
for(int i=1;i<=n;i++)assert(a[i]==0);
}
}
signed main(){
#ifdef do_while_true
// assert(freopen("data.in","r",stdin));
// assert(freopen("data.out","w",stdout));
#endif
int T=1;
// int i=1;
read(T);
while(T--){
// cerr << i << '\n';
// puts("");++i;
solve();
// Line;
}
#ifdef do_while_true
// cerr<<'\n'<<"Time:"<<1.0*clock()/CLOCKS_PER_SEC*1000<<" ms"<<'\n';
#endif
return 0;
}
第二种做法代码:
#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<ctime>
#include<random>
#include<assert.h>
#define pb emplace_back
#define mp make_pair
#define fi first
#define se second
#define dbg(x) cerr<<"In Line "<< __LINE__<<" the "<<#x<<" = "<<x<<'\n'
#define dpi(x,y) cerr<<"In Line "<<__LINE__<<" the "<<#x<<" = "<<x<<" ; "<<"the "<<#y<<" = "<<y<<'\n'
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int>pii;
typedef pair<ll,int>pli;
typedef pair<ll,ll>pll;
typedef pair<int,ll>pil;
typedef vector<int>vi;
typedef vector<ll>vll;
typedef vector<pii>vpii;
typedef vector<pil>vpil;
template<typename T>T cmax(T &x, T y){return x=x>y?x:y;}
template<typename T>T cmin(T &x, T y){return x=x<y?x:y;}
template<typename T>
T &read(T &r){
r=0;bool w=0;char ch=getchar();
while(ch<'0'||ch>'9')w=ch=='-'?1:0,ch=getchar();
while(ch>='0'&&ch<='9')r=r*10+(ch^48),ch=getchar();
return r=w?-r:r;
}
template<typename T1,typename... T2>
void read(T1 &x,T2& ...y){read(x);read(y...);}
const int mod=998244353;
inline void cadd(int &x,int y){x=(x+y>=mod)?(x+y-mod):(x+y);}
inline void cdel(int &x,int y){x=(x-y<0)?(x-y+mod):(x-y);}
inline int add(int x,int y){return (x+y>=mod)?(x+y-mod):(x+y);}
inline int del(int x,int y){return (x-y<0)?(x-y+mod):(x-y);}
int qpow(int x,int y){
int s=1;
while(y){
if(y&1)s=1ll*s*x%mod;
x=1ll*x*x%mod;
y>>=1;
}
return s;
}
#define Win do{puts("YES");return ;}while(0)
#define Lose do{puts("NO");return ;}while(0)
#define Alice do{puts("Alice");return ;}while(0)
#define Bob do{puts("Bob");return ;}while(0)
#define Line cerr << "----------\n"
const int N=200010;
int n;
int a[N];
void solve(){
read(n);
int mn=1;
for(int i=1;i<=n;i++)read(a[i]),cmin(mn,a[i]),a[i]^=a[i-1];
if(a[n]||mn==1)Lose;
if(n&1){
puts("YES");
cout << n-1 << '\n';
for(int i=n-2;i>=1;i-=2)cout << i << ' ';
for(int i=1;i<=n-2;i+=2)cout << i << ' ';
puts("");
}
else{
int p=0;
for(int i=1;i<=n;i+=2)
if(a[i]==0)
p=i;
if(!p)Lose;
puts("YES");
cout << n-2 << '\n';
for(int i=p-2;i>=1;i-=2)cout << i << ' ';
for(int i=1;i<=p-2;i+=2)cout << i << ' ';
for(int i=n-2;i>=p+1;i-=2)cout << i << ' ';
for(int i=p+1;i<=n-2;i+=2)cout << i << ' ';
puts("");
}
}
signed main(){
#ifdef do_while_true
// assert(freopen("data.in","r",stdin));
// assert(freopen("data.out","w",stdout));
#endif
int T=1;
// int i=1;
read(T);
while(T--){
solve();
// Line;
}
#ifdef do_while_true
// cerr<<'\n'<<"Time:"<<1.0*clock()/CLOCKS_PER_SEC*1000<<" ms"<<'\n';
#endif
return 0;
}