专栏文章
题解:P11406 [RMI 2020] 零和 / Sum Zero
P11406题解参与者 2已保存评论 1
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @min589on
- 此快照首次捕获于
- 2025/12/01 20:46 3 个月前
- 此快照最后确认于
- 2025/12/01 20:46 3 个月前
首先前面的部分和其他题解是相同的,即找到最小的 使得 中存在一个零段。
这显然是可以倍增解决的,但是我们只能开 个 int 数组了。
所以 4 进制倍增就好了,时间复杂度 。
CPP#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
using ll=long long;
const int N=4e5+9;
const int lgN=9e0;
int a[N],f[N][lgN],n,q;
signed main(){
cin.tie(0),cout.tie(0);
ios::sync_with_stdio(0);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
vector<ll> b(a,a+n+1);
partial_sum(b.begin(),b.end(),b.begin());
sort(b.begin(),b.end());
b.erase(unique(b.begin(),b.end()),b.end());
ll tmp=0;
for(int i=0;i<=n;tmp+=a[++i]) a[i]=lower_bound(b.begin(),b.end(),tmp)-b.begin()+1;
b.clear();
b.shrink_to_fit();
b.resize(n+1,n+1);
for(int i=n;i>=0;i--) f[i][0]=b[a[i]],b[a[i]]=i;
for(int k=0;k<lgN;k++) f[n+1][k]=n+1;
for(int i=n;i>=0;i--) f[i][0]=min(f[i+1][0],f[i][0]);
for(int k=1;k<lgN;k++){
for(int i=0;i<=n;i++) f[i][k]=f[f[f[f[i][k-1]][k-1]][k-1]][k-1];
}
cin>>q;
while(q--){
int l,r;
cin>>l>>r;
l--;
int ans=0;
for(int k=lgN-1;~k;k--){
while(f[l][k]<=r) l=f[l][k],ans+=1<<(k<<1);
}
cout<<ans<<endl;
}
return 0;
}
相关推荐
评论
共 1 条评论,欢迎与作者交流。
正在加载评论...