余姚培训每日题解-解题报告
4.17
A
给定一个无向图,求给每条边定向的方案数,使得图中没有环。
DAG计数的套路,我们还是枚举出度为0的点的集合,但是这样可能会重复枚举,所以要套一个-1的系数。
于是我们要做形如:
的卷积,类比<州区划分>的做法,我们多记一维
B
这是一道...我也不知道该如何评价的题。
经典的字典序贪心,考虑
4.18
A
首先把题意转化为每个点有权值,然后区间覆盖,询问没有覆盖过的点的权值和,支持撤销一次覆盖。
我们对询问进行,拆分,然后树剖,然后...?我就看题解去了。发现,我们只需要覆盖次数为0的地方的值——这是什么?这是覆盖次数的区间最小值!我们可以用线段树维护区间最小值的出现次数,这样就可以修改了!
B
需要前置知识:类欧。学习去了。看<类欧-学习笔记>吧
C
我们把当前区间的状态转化为一个点
4.17
A
显然的贪心,如何去掉log?我们从大到小枚举,用并查集找到最深的包含他的点。注意一个点可能有多个顾客!
B
论NTT被n^2爆踩
有一些性质:
我们选的图不会有环,因为这样就肯定可以去掉一条正边。假设正负数都有,那么每个正数一定会和负数连,然后负数之间相互连(因为每个点必须有边,所以不能都和最小的负数连)。把负数按绝对值从小到大排序,正数一定匹配的是一段后缀,我们枚举这段后缀的长度,正数从小到大依次匹配,多余的都和最后的负数匹配。
然后我们要处理前边cnt-i或cnt-i+1(后缀的第一个的负数可能之前的一起连边)。如果它们组成一个联通块,那么肯定是都和第一个(绝对值最小)的负数匹配。否则一定是(((())))))),也就是前边对称着连边,后边都和第一个连,我们暴力枚举中间点DP即可。
C
有m个区间,你可以在
一道提高组的题目...感觉我好傻...首先我们可以处理出每个可行的区间,然后我们直接DP!
遇到贡献与若干区间有关的问题,难以处理区间相交的决策,尝试区间DP,只考虑被
4.19
A
刚写完string状压牛逼,然后sbczy就改时限重测了
把
B
很多细节的贪心和模拟,咕了。
C 最大子段和
移项,讨论max的取向。发现在每个负数之间,是单调的,用一个指针指即可。
#define N 5005
const int inf=1e9;
int n,K;
int a[N],sum[N];
int dp[N][N]; // j = cnt of -1; [1...i]
signed main()
{
#ifdef M207
freopen("in.in","r",stdin);
// freopen("ot.out","w",stdout);
#endif
in(n,K);
if(n==1)
{
puts("0");
return 0;
}
for(ri i=1; i<=n; ++i) in(a[i]);
int s; dp[0][1]=s=max(a[1],0);
for(ri i=2; i<=n; ++i)
{
dp[0][i]=max(dp[0][i-1],s+K+max(a[i],0));
if(a[i]<0) s=0;
else s+=K+a[i];
}
sum[1]=a[1];
for(ri i=2; i<=n; ++i) sum[i]=sum[i-1]+K+a[i];
for(ri j=1; j<n; ++j)
{
for(ri i=1; i<=j; ++i) dp[j][i]=inf;
int lst=j,mxp=j+1;
for(ri i=j+1; i<=n; ++i)
{
s=sum[i]-(a[i]<0?a[i]:0);
dp[j][i]=max(dp[j-1][i-1],a[i]); // place -1 between i-1 and i
ckmin(dp[j][i],max(dp[j][lst],s-sum[lst])); // not place -1
while(mxp<i&&dp[j-1][mxp-1]<=s-sum[mxp]+a[mxp]) ++mxp;
if(mxp-1>lst) ckmin(dp[j][i],s-sum[mxp-1]+a[mxp-1]);
if(mxp<i) ckmin(dp[j][i],dp[j-1][mxp-1]);
if(a[i]<0) lst=i,mxp=i+1;
}
}
s=sum[n]-(a[1]<0?a[1]:0)-(a[n]<0?a[n]:0);
int ans=s-dp[0][n];
for(ri i=1; i<n; ++i) ckmax(ans,s-i*(K+1)-dp[i][n]);
out(ans);
return 0;
}
4.20
今天的题好自闭啊
B 幻方
我也不会证明,记一下结论:
在大部分情况下,
当n=4且m是偶数时,答案要乘2
C 再放送
疯狂讨论题。
int f[N],g[N],h[N]; // first come no fa; second come no fa; first come with fa
int w[N]; // into x, back to fa
void dfs(int x,int _fa)
{
for(solid v:E[x])
{
if(v==_fa) continue;
dfs(v,x);
inc(w[x],mul(iv[du[v]],iv[du[x]])); // immediately go back
inc(w[x],mul(w[v],iv[du[x]-1])); // ban the son
}
w[x]=mul(w[x],iv[du[x]]); // choose one son to go
}
void efs(int x,int _fa)
{
if(!sn[x])
{
f[x]=g[x]=val[x];
return;
}
int sf=0;
for(solid v:E[x])
{
if(v==_fa) continue;
efs(v,x); inc(sf,f[v]);
}
for(solid v:E[x])
{
if(v==_fa) continue;
// f
// immediately go back
inc(f[x],mul(iv[du[v]],iv[sn[x]],add(g[v],sf,md-f[v])));
// into the son & no back
inc(f[x],h[v]);
// into the son & back (ban the son)
inc(f[x],mul(w[v],iv[sn[x]-1],sub(sf,f[v])));
if(sn[x]==1) inc(f[x],mul(w[v],val[x]));
// g
// into the son & no back
inc(g[x],f[v]);
// h
// immediately go back
inc(h[x],mul(iv[du[v]],iv[du[x]],add(g[v],sf,md-f[v])));
// into the son & no back
inc(h[x],h[v]);
// into the son & back (ban the son)
inc(h[x],mul(w[v],iv[du[x]-1],sub(sf,f[v])));
}
f[x]=mul(f[x],iv[sn[x]]);
g[x]=mul(g[x],iv[sn[x]]);
h[x]=mul(h[x],iv[du[x]]);
}
4.21
A
又是rho和exgcd拼起来。这里我们知道pq的差较小,我们可以枚举x,y,尝试把n分解为
剩下俩题是计算几何...
4.22
A
线性基水题
BC摸了。