「杂题乱刷2」CF1996G

题目链接

CF1996G Penacony

解题思路

考虑把约束都记录到 \(a_i\) 上,\(a_i\) 表示 \(i \sim i + 1\) 受到的约束个数。

那么约束显然可以使用 xor hash 的形式来表示,我们只需要随机一个 \(val\),对于每个约束 \(l,r\),都将 \(a_{l \sim r - 1}\) 都异或上 \(val\) 即可,那么这个约束表述形式显然可以使用差分异或来维护。

还原时只需要将每个 \(i \in [1,n-1]\)\(pre_i \gets pre_i \oplus pre_{i-1}\) 即可,下文设 \(a\) 为还原后的 \(pre\)

\(ans\)\(a\) 数组的众数出现次数,答案即为 \(n - ans\),因为你完全可以将受到的约束取反,将所有值相等\(a_i\) 变成 \(0\),而 \(a_i\) 一旦变成 \(0\),这意味着 \(i\)\(i + 1\) 这个路径没有任何约束,因此一定是不用铺设道路的。

时间复杂度 \(O(n \log n)\)

参考代码

ll n,m;
ll a[1000010];
ll pre[1000010];
ll sum[1000010];
ll ans;
map<ll,ll>mp;
ll Ss=chrono::steady_clock::now().time_since_epoch().count();mt19937_64 Apple(Ss);ll rand_lr(ll l,ll r){return Apple()%(r-l+1)+l;}
void _clear(){}
void solve()
{
    ans=1e18;
    _clear();
    cin>>n>>m;
    forl(i,1,n*2)
        pre[i]=0;
    forl(i,1,m)
    {
        ll x,y;
        cin>>x>>y;
        ll num=rand_lr(1,1e18);
        pre[x]^=num,pre[y]^=num;
    }
    forl(i,1,n)
        pre[i]^=pre[i-1];
    ll maxn=0;
    forl(i,1,n)
        Max(maxn,++mp[pre[i]]);
    cout<<n-maxn<<endl;
    mp.clear();
}
posted @ 2025-04-09 15:21  wangmarui  阅读(18)  评论(0)    收藏  举报