【学习笔记】CF1458D Flip and Reverse

文章讨论了一种神奇的操作,将序列中的1视为+1,0视为-1,然后计算前缀和。通过对前缀和相同的元素进行翻转,实际上实现了序列的特定区间翻转。构建了一个无向图G,并证明了无论如何操作,图G保持不变,且每个序列对应一个欧拉路径。提出了通过贪心策略找到字典序最小的欧拉路径,算法时间复杂度为O(n)。
摘要由CSDN通过智能技术生成

这题妙啊。在学长的精心讲解下大概搞懂了。

首先这个操作就很神奇。考虑将 1 1 1看成 + 1 +1 +1 0 0 0看成 − 1 -1 1,求出其前缀和数组,然后每次就是两个前缀和相同的位置进行翻转,更神奇的是因为位置和值同时翻转了,所以你发现相当于是把前缀和数组的区间 [ l , r ] [l,r] [l,r]拿来翻转了。

于是就有一些更神奇的操作了。考虑构造无向图 G = ( V , E ) G=(V,E) G=(V,E),其中 V = { s u m i } V=\{sum_i\} V={sumi} E = { ( s u m i − 1 , s u m i ) ∣ 0 ≤ i < n } E=\{(sum_{i-1},sum_i)|0\le i<n\} E={(sumi1,sumi)∣0i<n},发现无论怎么操作这个序列对应的 G G G都是不变的,并且一个序列恰好经过所有边一次所以对应一个欧拉路径,那么大胆猜测一个欧拉路径和序列构成双射关系(?)。或者也可以换一个角度来看,相当于一个环可以顺时针或者逆时针走。并且这个图非常神奇, i i i只可能连到 i − 1 i-1 i1或者 i + 1 i+1 i+1,所以据此贪心的求出字典序最小的欧拉路径是容易的。

复杂度 O ( n ) O(n) O(n)

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
const int N=5e5+5;
int T,n,Min,sum[N],edges[N][2];
string s;
void dfs(int x){
    if(edges[x][0])assert(x);
    if(!edges[x][0]&&!edges[x][1])return;
    if(edges[x][0]&&edges[x-1][1]>1||!edges[x][1]){
        cout<<0;edges[x][0]--,edges[x-1][1]--,dfs(x-1);
    }
    else {
        cout<<1;edges[x][1]--,edges[x+1][0]--,dfs(x+1);
    }
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    cin>>T;
    while(T--){
        cin>>s,n=s.size();Min=0;sum[0]=0;
        for(int i=1;i<=n;i++){
            sum[i]=sum[i-1]+(s[i-1]=='1'?1:-1);
            Min=min(Min,sum[i]);
        }for(int i=0;i<=n;i++){
            sum[i]-=Min;
        }for(int i=0;i<=n;i++)edges[i][0]=edges[i][1]=0;
        for(int i=0;i<n;i++){
            if(s[i]=='1'){
                edges[sum[i]][1]++;
                edges[sum[i+1]][0]++;
            }
            else{
                edges[sum[i]][0]++;
                edges[sum[i+1]][1]++;
            }
        }
        dfs(sum[0]);cout<<"\n";
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值