test42
寻雾启示
首先最终的走法一定是找到位置序列 \(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;
}