2024-03-07
做题
埃及分数
迭代加深搜索
两层迭代:单位分数的个数 \(depth\) 和最大的分母 \(mxs\)
推枚举的当前分母 \(p\) 的上下界:
- \(\frac{1}{p}\le \frac{a}{b}\) 即 \(p \ge \frac{b}{a}\)
- 每一个单位分母不相同,所以 \(p \ge last\)
- 要在后面 \(depth-k+1\) 个分数凑出当前的 \(\frac{a}{b}\) 每个最大是 \(\frac{1}{p}\),所以
- 要保证当前选了 \(p\) 之后,剩下的 \(depth-k\) 个单位分数还有的选,即
解得
\[p \ge \frac{b\times mxs}{a\times mxs-b\times (depth-k)} \]综上
\[p\in [\max(last,\frac{b\times mxs}{a\times mxs-b\times (depth-k)},\frac{b}{a}),\min(S,\frac{b\times (depth-k+1)}{a})] \]还有优化:只剩最后两个分数的时候 \((k=depth-1时)\) 的特殊情况
设最后两个单位分数分母为 \(x, y\) ,则 \(\frac{a}{b}=\frac{1}{x}+\frac{1}{y}\)
整理得
由韦达定理将 \(x, y\) 转化为一元二次方程 \(x^2-azx+bz\) 的两个不等实根
令 \(\Delta = a^2z^2-4bz, s=\sqrt{\Delta}\)
则
枚举 \(z\) ,判断 \(\Delta\) 是否是平方数,再判断 \(az+\sqrt{\Delta}\) 是否是偶数即可
求 \(z\) 的范围:
\[az=x+y,bz=xy \\ x, y\le S \\ \therefore az \le 2\times S,bz \le S^2 \\ \therefore z \le min(\frac{2S}{a},\frac{S^2}{b}) \]统计答案:
当 \(k=depth\) 时,判断 \(a\) 是否等于 \(1\),\(b\) 是否大于 \(last\) ,再比较全局答案数组的 \(ans_k\) 和 当前存的答案数组的 \(tmp_k\) 比较,若当前更小,更新答案
k短路
A*算法
A* 是 dijkstra 的升级版
建反图跑一边最短路,求出每个点的 启发函数 \(h\)
再正着bfs,设从起点到当前点的距离为 \(g\) ,估价函数为 \(f=g+h\)
把节点加入优先队列,每次取出 \(f\) 值最小的节点更新其它点
第 \(k\) 次经过终点时就是 k短路
Tips:
- vector可以直接比较字典序的大小
数列分块入门2
题目描述:给出一个长为 \(n\) 的数列,以及 \(n\) 个操作,操作涉及区间加法,询问区间内小于某个值 \(x\) 的元素个数。
块内排好序,存排完序之后的位置用于单点加
整块的直接加到 tag 上,边角暴力加,然后重新排这一块的序
查询的时候块内 lower_bound 边角暴力查
代码
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=50050;
const int Inf=2e9;
int n;
int len;
pair<int,int> w[N];
int blk[N],pos[N],tag[N];
int lft[N],rgh[N];
int lwrbnd(int l,int r,int x) {
l--,r++;
while(r-l>1) {
int m=l+r>>1;
if(w[m].first<x) l=m;
else r=m;
}
return l+1;
}
int main() {
scanf("%d",&n);
len=sqrt(n);
for(int i=1;i<=n;i++) blk[i]=(i-1)/len+1,lft[blk[i]]=Inf,rgh[blk[i]]=-Inf;
for(int i=1;i<=n;i++) lft[blk[i]]=min(lft[blk[i]],i),rgh[blk[i]]=max(rgh[blk[i]],i);
for(int i=1;i<=n;i++) scanf("%d",&w[i].first),w[i].second=i;
for(int i=1;i<=(n-1)/len+1;i++) sort(w+lft[i],w+rgh[i]+1);
for(int i=1;i<=n;i++) pos[w[i].second]=i;
for(int o=1;o<=n;o++) {
int opt,l,r,x;
scanf("%d%d%d%d",&opt,&l,&r,&x);
if(opt==0) {
for(int i=l;i<=min(r,rgh[blk[l]]);i++) w[pos[i]].first+=x;
sort(w+lft[blk[l]],w+rgh[blk[l]]+1);
for(int i=lft[blk[l]];i<=rgh[blk[l]];i++) pos[w[i].second]=i;
if(blk[l]!=blk[r]) {
for(int i=lft[blk[r]];i<=r;i++) w[pos[i]].first+=x;
sort(w+lft[blk[r]],w+rgh[blk[r]]+1);
for(int i=lft[blk[r]];i<=rgh[blk[r]];i++) pos[w[i].second]=i;
}
for(int i=blk[l]+1;i<blk[r];i++) tag[i]+=x;
}
else {
x=x*x;
int ans=0;
for(int i=l;i<=min(r,rgh[blk[l]]);i++) if(w[pos[i]].first<x-tag[blk[l]]) ans++;
if(blk[l]!=blk[r]) for(int i=lft[blk[r]];i<=r;i++) if(w[pos[i]].first<x-tag[blk[r]]) ans++;
for(int i=blk[l]+1;i<blk[r];i++) ans+=(lwrbnd(lft[i],rgh[i],x-tag[i])-lft[i]);
printf("%d\n",ans);
}
}
return 0;
}
标签:03,le,frac,07,int,mxs,times,2024,depth
From: https://www.cnblogs.com/Orange-Star/p/18059645