daliy
D. For Gamers. By Gamers. (思维)2000
https://codeforces.com/problemset/problem/1657/D
题解:式子很好列,HD<=x*hd,但由于x为整数,无法维护c/hd的值进行二分,我们进一步观察,发现C<=1e6,且对于有相同c的单位,只有战斗力最高的有用,故我们可以尝试维护每个c时所能得到的最大战斗力。我们遍历每个有用的单位,用其更新所有ci的倍数的最大战斗力,复杂度为C(1/1+1/2+1/3+...+1/C)=ClogC,然后维护前缀最大值得到花费<=c时能得到的最大战斗力。由于其不减,故可以对于每个怪兽二分出最小花费。
D. Optimal Partition (树状数组,dp)2100
https://codeforces.com/contest/1668/problem/D
题解:首先分析区间的性质,对于贡献为0和负数的区间,其长度至多为1,下给出证明:
对于贡献为0的区间,若其长为2k,我们将其分为两等长部分结果不会更劣,若长度为2k+1,则分为k,1,k形式,若两端都>=0,则就这样划分,否则将中间段加入正的一端必然为正,故这样划分不会更劣,不断划分下去长度只有1.
对于贡献为负的区间,分割后无论如何都不会更劣,故可最终划分为长度为1的区间。
我们知晓了只有贡献为正的区间可以>1。我们先列出转移方程,f[i]=max(f[i],f[j]+i-j)(其中[j,i]>0),显然若暴力转移是n2,要想优化需维护出前i项满足条件的f[j]-j的最大值,如何才能满足条件?只要前缀和s[i]>s[j-1],[j,i]段即满足条件。
故我们可以按前缀和排序后,按此序用树状数组维护前缀最大值,每次执行更新即可。
#define int long long
using namespace std;
const int N=5e5+100;
int c[N],f[N],a[N],s[N],g[N];
pair<int,int> b[N];
int n;
void add(int x,int k){
for(;x<=n;x+=x&-x) c[x]=max(c[x],k);
}
int ask(int x){
int res=-1e9;
for(;x;x-=x&-x) res=max(res,c[x]);
return res;
}
void solve(){
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i],s[i]=s[i-1]+a[i],b[i]={s[i],-i};
sort(b+1,b+n+1);
for(int i=1;i<=n;i++){
g[-b[i].second]=i;
}
for(int i=1;i<=n;i++) c[i]=-1e9,f[i]=0;
for(int i=1;i<=n;i++){
int w;
if(a[i]>0) w=1;
else if(a[i]<0) w=-1;
else w=0;
f[i]=f[i-1]+w;
int pmax=ask(g[i]);
f[i]=max(f[i],pmax+i);
if(s[i]>0) f[i]=i;
add(g[i],f[i]-i);
}
cout<<f[n]<<endl;
}
signed main(){
int T;cin>>T;
while(T--)
solve();
}
B. Long Legs
https://codeforces.com/contest/1814/problem/B
题解:虽然是B题但还是有点意思的,我们想要得到到(x,y)的最小组数,首先贪心的想,必定是先升级再跳更好,然而有时候需要跳至多一次(余数<除数)满足整除条件,对于这种先充能再跳跃的问题显然可以用根号分治充能次数,对于<3sqrt(N)的情况我们可以枚举处理,对于>3sqrt(N)时,其可以通过至多3*sqrt(N)步完成,故后续无需考虑。之后枚举y+\(\lceil y/i \rceil\)+ \(\lceil x/i \rceil\)-1即可得到答案。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10;
void solve(){
int a,b,ans=1e18,x=0,y;cin>>a>>b;
if(a>b) swap(a,b);
for(int i=1;i<=200000;i++){
int e=i+(b+i-1)/i-1;
ans=min(ans,e+(a+i-1)/i);
}
cout<<ans<<endl;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int T;cin>>T;
while(T--) solve();
}

浙公网安备 33010602011771号