[考试反思]0329省选模拟57:细节
Posted hzoi-deepinc
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[考试反思]0329省选模拟57:细节相关的知识,希望对你有一定的参考价值。
最近细节总是挂总是挂总是挂。我说我$T2$估分$62$有人信吗?
有没有人信不重要。反正是没拿到。而且直接爆零了。
原因是变量名写反了且少了一种情况(想到了忘写了)。这怕不是个弱智吧。。。
大样例看起来挺大的,然后都跑过了,我以为不说$62$,$48$也应该是稳了。
时间分配还是奇奇怪怪的,反正就是莫名的时间不够。
$T2$研究了好久,$T3$也想了挺长时间。
然后一直觉得$T1$很神仙(看数据范围不像什么常规的多项式复杂度$dp$,没往状压上想)于是最后只给它留了半小时左右。
然后发现,好像出题人说它是签到题这是真的,于是就开始写,发现复杂度好像有点高(然而其实已经$AC$了)
于是剩下的时间都拿去剪枝卡常什么的,再也没有看一眼我爆零的$T2...$
改题的时候又自闭了。因为有下发数据于是一直没有写对拍,但是下发数据又太大,于是一直干瞪着。
然后问别人也大都不给我看于是磨磨蹭蹭将近$6$小时就过去了。
结果最后还是对拍小数据发现了问题,然后就$A$掉了。
考后对拍也是真有用啊。。。
T1:Max
大意:初始为空的序列$A$长为$n$。$m$轮操作第$i$轮有$p_{i,j,k}$的概率使得$A_j + = k$。其中$0le k le c$
求所有操作后整个序列最大值的期望。$n le 40,c‘le 3 ,m le 10$
数据范围小的奇怪。$m$在状压范围内。
于是就状压$m$表示这个子集的轮是否已经被分配给其它人。做一个背包$dp$就行了。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define mod 1000000007 4 int n,m,c,p[55][11][5],dp[1025][33],bp[1025][33],t[33],ans,bt[1025],pre[1025][33]; 5 int main(){//freopen("max3.in","r",stdin); 6 cin>>n>>m>>c; 7 for(int i=1;i<=m;++i)for(int j=1;j<=n;++j)for(int k=0;k<=c;++k)scanf("%d",&p[j][i][k]); 8 const int mst=(1<<m)-1; 9 for(int i=1;i<=mst;++i)bt[i]=bt[i^i&-i]+c; 10 dp[mst][0]=1; 11 for(int i=1;i<=n;++i){ 12 memset(bp,0,sizeof bp);memset(pre,0,sizeof pre); 13 for(int s=mst;~s;--s){ 14 bp[s][0]=1; 15 for(int j=1;j<=m;++j)if(s&1<<j-1){ 16 for(int y=0;y<=bt[s];++y)for(int x=0;x<=c;++x)t[y+x]=(t[y+x]+1ll*bp[s][y]*p[i][j][x])%mod; 17 for(int y=0;y<=bt[s];++y)bp[s][y]=t[y],t[y]=0; 18 } 19 pre[s][0]=bp[s][0]; 20 for(int y=1;y<=bt[s];++y)pre[s][y]=(pre[s][y-1]+bp[s][y])%mod; 21 } 22 for(int s=1;s<=mst;++s)for(int x=0;x<=bt[mst^s];++x)if(dp[s][x]) 23 for(int u=s;u;u=u-1&s){ 24 dp[s^u][x]=(dp[s^u][x]+1ll*dp[s][x]*pre[u][min(bt[u],x)])%mod; 25 for(int y=x+1;y<=bt[u];++y)dp[s^u][y]=(dp[s^u][y]+1ll*dp[s][x]*bp[u][y])%mod; 26 } 27 }for(int i=1;i<=bt[mst];++i)ans=(ans+1ll*i*dp[0][i])%mod; cout<<ans<<endl; 28 }
T2:paint
大意:$w imes h$的矩阵中有$n$特殊点,要求选定一个周长最大的矩形使得其内部不含特殊点(不含边框)。$nle 10^5,w,h le 10^8$
发现任意一个$1 imes h$或$w imes 1$的矩形都一定合法。所以答案大于等于$(max(w,h)+1) imes 2$
所以说它一定越过了$x=frac{x}{2}$或$y=frac{h}{2}$。以前者为例,做扫描线,枚举矩形右边界。
用一个线段树维护每个点作为左端点的收益,即维护$max(-l+u-d)$。然后可以发现$u,d$的取值关于左端点单调,形式是单调栈。
所以就这么维护一下,线段树区间加全局$max$。要注意各种边界。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define S 611111 4 unordered_map<int,int>X; vector<int>Y[S]; 5 int n,w,h,ans,rx[S],x[S],y[S],u[S],ul[S],ut,d[S],dl[S],dt,v[S<<2],lz[S<<2],c,z,H; 6 #define lc p<<1 7 #define rc lc|1 8 #define md (L+R>>1) 9 void build(int p,int L,int R){lz[p]=0; 10 if(L==R){v[p]=-rx[L];return;} 11 build(lc,L,md); build(rc,md+1,R); v[p]=max(v[lc],v[rc]); 12 } 13 void add(int l,int r,int w,int p=1,int L=0,int R=c){if(r<l)return;//f(p==1)cerr<<l<<‘ ‘<<r<<‘ ‘<<w<<endl; 14 if(l<=L&&R<=r){v[p]+=w;lz[p]+=w;return;} 15 if(lz[p])v[lc]+=lz[p],v[rc]+=lz[p],lz[lc]+=lz[p],lz[rc]+=lz[p],lz[p]=0; 16 if(l<=md)add(l,r,w,lc,L,md); if(r>md)add(l,r,w,rc,md+1,R); v[p]=max(v[lc],v[rc]); 17 } 18 void solve(){ 19 memset(rx,0,sizeof rx); 20 H=h/2; n=z; X.clear(); 21 for(int i=1;i<=z;++i)rx[i]=x[i],x[++n]=x[i],y[n]=0,x[++n]=x[i],y[n]=h; 22 x[++n]=w;y[n]=0; x[++n]=0;y[n]=0; x[++n]=0;y[n]=h; x[++n]=w;y[n]=h; rx[n-1]=0; rx[n]=w; 23 sort(rx+1,rx+1+n); c=unique(rx+1,rx+1+n)-rx-1; 24 for(int i=1;i<=c;++i)X[rx[i]]=i; 25 for(int i=1;i<=n;++i)Y[X[x[i]]].push_back(y[i]); 26 build(1,0,c); 27 u[0]=H; d[0]=H+1; ut=dt=0; 28 for(int r=1;r<=c;++r){ 29 add(r-1,r-1,h);ans=max(ans,rx[r]+v[1]);add(r-1,r-1,-h); 30 for(int a:Y[r])if(a<=H){ 31 if(dl[dt]==r&&d[dt]>=a)continue; 32 while(d[dt]<=a)add(dl[dt-1],dl[dt]-1,d[dt]),dt--; 33 add(dl[dt],r-1,-a);d[++dt]=a;dl[dt]=r; 34 }else{ 35 if(ul[ut]==r&&u[ut]<=a)continue; 36 while(u[ut]>=a)add(ul[ut-1],ul[ut]-1,-u[ut]),ut--; 37 add(ul[ut],r-1,a);u[++ut]=a;ul[ut]=r; 38 }Y[r].clear(); 39 } 40 } 41 int main(){ 42 cin>>w>>h>>n; z=n; 43 for(int i=1;i<=z;++i)scanf("%d%d",&x[i],&y[i]); 44 solve(); for(int i=1;i<=z;++i)swap(x[i],y[i]); swap(h,w); solve(); 45 cout<<ans*2<<endl; 46 }
T3:Decompose
大意:将树剖分成若干长度$le L$的链,对于每条链,其中深度第$i$大的点$p$会贡献$w[p][i]$。最大化整棵树的贡献。
每次单点修改权值之后,进行回答。$n ,qL le 10^5,2 le L le 4$
看一眼就知道是$ddp$。一如既往的难写。由于$T2$调太久了就没时间写了。
首先暴力肯定就是$dp[p][i]=sumlimits_{u in son(p)} (maxlimits_{j=1}^{L} dp[u][j]) + maxlimits_{u in son(p)} (f[p][i-1] - (maxlimits_{j=1}^{L} dp[u][j]))$
然后那个$max$可以用$set$维护。暴跳父亲复杂度是$O(n^2logn)$的。
然后套个$ddp$的板子把上面这玩意轻重儿子分开弄一个矩阵时间复杂度就变成$qlog^2nL^3+nL^3$
以上是关于[考试反思]0329省选模拟57:细节的主要内容,如果未能解决你的问题,请参考以下文章