C2. Prefix Flip (Easy&Hard Version) (思维)

Easy version

字符串长度n<=1000,可操作次数k<=3*n

Hard version

字符串长度n<=100000,可操作次数k<=2*n

题意: 给你两个二进制串a,b,每次对a操作你可以选择一个长度任意的前缀,在这个区间取反并且反转(0->1 1->0,再reverse),最后让a==b,输出步数及每一步选择的前缀长度,不用最大或最小化操作次数。

思路: easy version可以直接暴力,因为每次取前缀,所以优先匹配后面的,那么以后就不用管后面已经匹配好了的。如果a[i]==b[i]则不用管,否则看a[1]和b[i],如果a[1]==b[i],则先选择长度为1的前缀,让a[1]不等于b[i],再选择长度为i的前缀进行操作,这样就让b[i]成功匹配。

上述操作,遍历b,时间复杂度是O(n),暴力反转时间复杂度也是O(n),嵌套一下就是O(n^2),对于hard肯定不行。

仔细观察可以发现,我们每次操作,要么是让a[i]和b[i]配对,要么是让a[1]和b[i]配对,即每次从首尾去取舍,剩余的总是连续的某一段。所以我们可以用l和r记录剩余串的范围,fg表示这个串的状态,fg=0表示这个串是正向的,并且现在串中数据和原串一样,fg=1表示这个串是反向的,并且串中数组和原来相反,每次反转即改变fg就行了,最后只要从后往前遍历配对一遍b就行了。

easy version代码:

#include
#pragma GCC optimize("Ofast")
#define endl '\n'
#define null NULL
#define ls p<<1
#define rs p<<1|1
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define ll long long
#define int long long
#define pii pair
#define pdd pair
#define ull unsigned long long
#define all(x) x.begin(),x.end()
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ct cerr<<"Time elapsed:"<<1.0*clock()/CLOCKS_PER_SEC<<"s.\n";
char *fs,*ft,buf[1<<20];
#define gc() (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<20,stdin),fs==ft))?0:*fs++;
inline int read(){int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=gc();}
return x*f;}
using namespace std;
const int N=1e3+5;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
const double eps=1e-6;
const double PI=acos(-1);
char a[N],b[N];
signed main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        memset(a,0,sizeof a);
        memset(b,0,sizeof b);
        cin>>a+1;
        cin>>b+1;
        vector<int>ans;
        for(int i=n;i>=1;i--)
        {
            if(a[i]==b[i])
                continue;
            if(a[1]==b[i])
            {
                ans.pb(1);
                a[1]=(a[1]=='0'?'1':'0');
            }
            ans.pb(i);
            for(int j=1;j<=i;j++)
            {
                a[j]=(a[j]=='0'?'1':'0');
            }
            for(int j=1;j<=i/2;j++)
            {
                swap(a[j],a[i-j+1]);
            }
        }
        cout<<ans.size()<<' ';
        for(auto i:ans)
            cout<<i<<' ';
        cout<<endl;
    }
}

hard version代码:(也适用于easy version)

#include
#pragma GCC optimize("Ofast")
#define endl '\n'
#define null NULL
#define ls p<<1
#define rs p<<1|1
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define ll long long
#define int long long
#define pii pair
#define pdd pair
#define ull unsigned long long
#define all(x) x.begin(),x.end()
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ct cerr<<"Time elapsed:"<<1.0*clock()/CLOCKS_PER_SEC<<"s.\n";
char *fs,*ft,buf[1<<20];
#define gc() (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<20,stdin),fs==ft))?0:*fs++;
inline int read(){int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=gc();}
return x*f;}
using namespace std;
const int N=1e5+5;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
const double eps=1e-6;
const double PI=acos(-1);
char a[N],b[N];
signed main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        cin>>a+1;
        cin>>b+1;
        vector<int>ans;
        int l=1,r=n,fg=0;
        for(int i=n;i>=1;i--)
        {
            if(fg==0)
            {
                if(a[r]==b[i])
                {
                    r--;
                    continue;
                }
                if(a[l]==b[i])
                    ans.pb(1);
                ans.pb(i);
                l++;
                fg=1;
            }
            else
            {
                if(a[l]!=b[i])
                {
                    l++;
                    continue;
                }
                if(a[r]!=b[i])
                    ans.pb(1);
                ans.pb(i);
                r--;
                fg=0;
            }
        }
        cout<<ans.size()<<' ';
        for(auto i:ans)
            cout<<i<<' ';
        cout<<endl;
    }
}

你可能感兴趣的:(数学,贪心,构造等思维问题)