题解:P14925 [北大集训 2025] 异形工厂
Iruka_Okazaki · · 题解
发现每一次操作本质就是交换 1 的位置,其实每一次的操作就是位置 1 提取出来,假设下标分别为
发现如果有这个上取整很麻烦,所以先不考虑它。首先只有
对于一个区间,我们发现一个
接下来把可能会额外增加的
最后的复杂度为
code:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn = 1e6 + 10;
const int V = 1e6;
struct BIT
{
int c[maxn];
void init(){memset(c,0,sizeof(c));}
int lowbit(int u){return u & (-u);}
void update(int u,int val){while(u <= V){c[u] += val;u += lowbit(u);}}
int query(int u){int ans = 0;while(u > 0){ans += c[u];u -= lowbit(u);}return ans;}
int Find()
{
int p = 0,sum = 0;
for(int i = 18;i >= 0;i--)if(sum + c[p | (1 << i)])p |= (1 << i),sum += c[p];
return p + 1;
}
}C[2],W;
int res[maxn],ans[maxn],sp[maxn];map<int,int> mp;
int n,q,a[maxn],b[maxn],sum[maxn],pre[maxn];
void solve()
{
C[0].init();C[1].init();W.init();
int cnt = 0;
for(int i = 1;i <= n;i++)
{
if(a[i] > b[i])cnt++,C[i & 1].update(1,1),C[i & 1].update(cnt + 1,-1);
else if(cnt && a[i] < b[i])
{
int k = C[i & 1].Find();C[i & 1].update(1,-1);C[i & 1].update(k,1);
C[!(i & 1)].update(k,-1);C[!(i & 1)].update(cnt + 1,1);
W.update(k,1);W.update(cnt + 1,-1);res[i] += W.query(cnt) + abs(sp[i] - sp[pre[i]]);
W.update(cnt,-W.query(cnt));W.update(cnt + 1,-W.query(cnt + 1));cnt--;
}
}
}
signed main()
{
cin >> n >> q;mp[0] = 0;
for(int i = 1;i <= n;i++){char c;cin >> c;a[i] = c - '0';}
for(int i = 1;i <= n;i++){char c;cin >> c;b[i] = c - '0';}
for(int i = 1;i <= n;i++)
{
sp[i] = sp[i - 1] + (a[i] - b[i]) * i;
sum[i] = sum[i - 1] + a[i] - b[i];
pre[i] = mp[sum[i]];mp[sum[i]] = i;
}
solve();
for(int i = 1;i <= n;i++)swap(a[i],b[i]);
solve();
for(int i = 1;i <= n;i++)ans[i] = ans[pre[i]] + res[i] / 2;
while(q--)
{
int l,r;cin >> l >> r;
if(sum[r] != sum[l - 1])cout << "-1\n";
else if(l + 1 == r && a[l] != b[l])cout << "-1\n";
else cout << ans[r] - ans[l - 1] << '\n';
}
return 0;
}