「杂题乱刷2」CF1996G
题目链接
解题思路
考虑把约束都记录到 \(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();
}

浙公网安备 33010602011771号