雨水从黑云降临到了人间 果实脱落枝叶吸收于地面 时间流逝再也回不到从前 曾经珍藏回忆变成不可逆爱恋
test42
lgj 咬打火机。
萌熊比赛都来了 /fad
寻雾启示
首先最终的走法一定是找到位置序列 \(p_1,\dots,p_m\) 满足 \(p_i<p_{i+1},p_m=n\) 然后依次铺羊毛到 \(p_i\),为了不思考那么多,我们设 \(f_i\) 表示铺到 \(i\) 回到 \(1\) 的最小时间,转移显然是 \(f_i=\min\{\max(f_j,ik)+2t_1j+(i-j)(t_1+t_2)\}\),没有除了最开始那个 \(\max\{f_j,ik\}\) 没有 \(i,j\) 复合的项,独立出来看作常数,然后 \(f_j\) 显然 \(\uparrow\),所以我们可以双指针扫出两种贡献的区间,前面那个前缀 \(\max\),后面那个用 multiset 找出最大常数。
#include<bits/stdc++.h>
#define int long long
#define up(i,l,r) for(int i=l; i<=r; ++i)
#define dn(i,r,l) for(int i=r; i>=l; --i)
using namespace std;
const int N=100005, inf=1e18;
int T, m, k, t1, t2, f[N];
void mian() {
cin >> m >> k >> t1 >> t2, t1+=t2;
int j=1, ran=0;
multiset<int> coel;
coel.insert(inf);
up(i,1,m) {
while(j<i&&f[j]<i*k) {
coel.erase(coel.find(f[j]+(2*t2-t1)*j));
ran=min(ran,(2*t2-t1)*j++);
}
f[i]=min(ran+i*k,*coel.begin())+i*t1;
coel.insert(f[i]+(2*t2-t1)*i);
cout << f[i]-t2*i << ' ';
}
cout << '\n';
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> T;
while(T--) mian();
return 0;
}
青年晚报
题面写的真的好恶心。
首先发现 \(f/g\) 贡献独立,当成俩问题,自己多抄写几次,然后把算式组合意义一下,可以看作每个点有一个 \([0,m]\) 的初始等级,每次可以直接 \(\times 1\) 走到下一层,或者根据层数的 \(\text{odd/eve}\) 下降等级 \(\times (+/-)rk\) 走向下一层,注意等级始终在 \([0,m]\)。
那我们想想怎么考虑 \(f_i\to (F/G)_j\) 的贡献,首先 \(j\leq i\),等级下降绝对值系数有一个 \(\frac{i!}{j!}\),然后还想知道选择下降位置的系数,这个容易预处理出来,枚举走 \(l/r\) 次 \(+/1\) 用组合数乘正负然后贡献给 \(dp_{l+r}\) 即可。
#include<bits/stdc++.h>
#define int long long
#define up(i,l,r) for(int i=l; i<=r; ++i)
#define dn(i,r,l) for(int i=r; i>=l; --i)
using namespace std;
const int N=5005, P=1e9+7;
int n, m, f[N], g[N], F[N], G[N], mul[N], inv[N];
int l[N], r[N], sav[2][N];
inline int C(int x,int y) {
if(y<0||x<y) return 0;
int u=x-n/2, val=1;
if(sav[u][y]) return sav[u][y];
up(i,x-y+1,x) val=val*i%P;
up(i,1,y) val=val*inv[i]%P;
return sav[u][y]=val;
}
inline void add(int &a,int b) { a=(a+b)%P; }
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
mul[0]=inv[0]=inv[1]=1;
up(i,1,5000) mul[i]=mul[i-1]*i%P;
up(i,2,5000) inv[i]=inv[P%i]*(P-P/i)%P;
cin >> n >> m;
up(i,0,m) cin >> f[i];
up(i,0,m) cin >> g[i];
up(i,0,m) {
int L=n/2+(n%2==1), R=n/2;
up(j,0,i) add(l[i],C(L,j)*C(R,i-j)%P*(j%2==0?1:-1));
}
up(i,0,m) {
int L=n/2, R=n/2+(n%2==1);
up(j,0,i) add(r[i],C(L,j)*C(R,i-j)%P*(j%2==0?1:-1));
}
up(i,2,5000) inv[i]=inv[i-1]*inv[i]%P;
up(i,0,m) up(j,0,i) {
int v=l[j]*mul[i]%P*inv[i-j]%P*f[i]%P;
if(n%2==0) add(F[i-j],v); else add(G[i-j],v);
}
up(i,0,m) up(j,0,i) {
int v=r[j]*mul[i]%P*inv[i-j]%P*g[i]%P;
if(n%2==0) add(G[i-j],v); else add(F[i-j],v);
}
up(i,0,m) cout << (F[i]%P+P)%P << ' '; cout << '\n';
up(i,0,m) cout << (G[i]%P+P)%P << ' '; cout << '\n';
return 0;
}
寻宝游戏
如果 \(l+1=r\),那么必须同时操作俩,如果是 \(1,1\) 需要 \(1\) 次,如果是 \(1,2\) 答案是 \(-1\),别的都会变成 \(len=3\) 的问题,我们只用下面考虑 \(len\geq 3\) 的怎么做(虽然我写代码的时候很蠢地对这个进行了分类讨论)。
我们希望把所有的泡面扔到一个目标桶里面,我们分类考虑一下,首先目标桶一定是最大的 \((\text{odd/eve})a_i\),设去掉这个桶之后最大的桶有 \(sec\) 桶、总和为 \(sum\)。
- 若 \(2|sum\),理想型。
- 若 \(sec\leq sum-sec\),那么 \(\frac{sum}{2}\) 次得了。
- 若 \(sec>sum-sec\),那么 \(sec\) 是下界,并且操作 \(sec\) 次是可以做到的,\(sec-\frac{sum}{2}+\frac{sum}{2}\) 说是。
-
若 \(2\nmid sum\),不算理想(?
此时必须调整目标桶,不然奇偶性永远对不上,然后就变成上面那种了喵 >w<
#pragma GCC optimize(1,2,3,"Ofast","inline")
#include<bits/stdc++.h>
#define int long long
#define up(i,l,r) for(int i=l; i<=r; ++i)
#define dn(i,r,l) for(int i=r; i>=l; --i)
using namespace std;
const int N=300005, M=21, inf=1e18;
int Pluto, n, T, q, a[N], s[N], odd[N][M], eve[N][M], fc[N], lg[N];
inline int Odd(int l,int r) {
if(l>r) return 0;
int k=lg[r-l+1], x=odd[l][k], y=odd[r-(1<<k)+1][k];
return a[x]>a[y]?x:y;
}
inline int Eve(int l,int r) {
if(l>r) return 0;
int k=lg[r-l+1], x=eve[l][k], y=eve[r-(1<<k)+1][k];
return a[x]>a[y]?x:y;
}
int ran(vector<int> sav) {
int res=0;
for(int u:sav) if(a[u]>a[res]) res=u;
return res;
}
void mian() {
cin >> n >> q, T=log2(n);
up(i,1,n) {
cin >> a[i];
fc[i]=fc[i-1]+(a[i]==1);
s[i]=s[i-1]+a[i];
odd[i][0]=(a[i]%2==1?i:0);
eve[i][0]=(a[i]%2==0?i:0);
}
up(j,1,T) up(i,1,n-(1<<j)+1) {
int x=odd[i][j-1], y=odd[i+(1<<j-1)][j-1];
odd[i][j]=(a[x]>a[y]?x:y);
}
up(j,1,T) up(i,1,n-(1<<j)+1) {
int x=eve[i][j-1], y=eve[i+(1<<j-1)][j-1];
eve[i][j]=(a[x]>a[y]?x:y);
}
while(q--) {
int l, r, p, sum, sec, ans=inf;
cin >> l >> r;
if(l==r) { cout << 0 << '\n'; continue; }
if(fc[r]-fc[l-1]==r-l+1) { cout << (r-l+1)/2 << '\n'; continue; }
if(l+1==r) {
l=a[l], r=a[r];
if(r<l) swap(l,r);
if(l==1) {
if(r==1) { cout << 1 << '\n'; continue; }
if(r==2) { cout << -1 << '\n'; continue; }
p=r-2;
if(p==1) cout << 3 << '\n';
if(p==2) cout << 4 << '\n';
if(p>2) cout << 5 << '\n';
}
else {
--l, --r;
if(l==1) {
if(r==1) cout << 2 << '\n';
if(r==2) cout << 3 << '\n';
if(r>2) cout << 4 << '\n';
continue;
}
if(l==2) { cout << 3 << '\n'; continue; }
if(l==r) { cout << l+1 << '\n'; continue; }
if(l%2==1) cout << 2+max(l-1,(l+3)/2) << '\n';
else cout << 1+max(l,(l+2)/2) << '\n';
}
continue;
}
if(p=Odd(l,r)) {
sum=s[r]-s[l-1]-a[p];
sec=a[ran({Odd(l,p-1),Eve(l,p-1),Odd(p+1,r),Eve(p+1,r)})];
int res=max(sum/2,sec);
if(sum%2==1) res=max((sum+1)/2,sec-1)+1;
ans=min(ans,res);
}
if(p=Eve(l,r)) {
sum=s[r]-s[l-1]-a[p];
sec=a[ran({Odd(l,p-1),Eve(l,p-1),Odd(p+1,r),Eve(p+1,r)})];
int res=max(sum/2,sec);
if(sum%2==1) res=max((sum+1)/2,sec-1)+1;
ans=min(ans,res);
}
cout << ans << '\n';
}
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
up(i,1,3e5) lg[i]=log2(i);
cin >> Pluto;
while(Pluto--) mian();
return 0;
}

浙公网安备 33010602011771号