9.3题解
Posted hzjuruo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了9.3题解相关的知识,希望对你有一定的参考价值。
T1
大家考场上都想到了暴搜,并且暴搜可以过,但是为什么还是有一大半的人$WA0$了呢,因为这题细节居多,考场上我调了到快9点,才过了大样例,结果还是逃脱不了$WA0$的命运,我太难了
其实思路上没有什么,你就枚举循环节的长度,把后面位置上有数字的对回来,看能不能合法就行了,记得疯狂调试
1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 #define inf 2139062143 7 #define maxm 10010 8 #define maxp 100100 9 using namespace std; 10 struct node 11 int p,x; 12 a[maxm]; 13 int t,c,m,js,tail,len,pd; 14 int b[maxp],lon[5],ma[5],st[5],mi[5],stt[5]; 15 vector <int> chan; 16 bool cmp(const node &a,const node &b) 17 18 return a.p<b.p; 19 20 int main() 21 22 // freopen("1.in","r",stdin); 23 // freopen("W.out","w",stdout); 24 scanf("%d%d",&t,&c); 25 while(t--) 26 27 scanf("%d",&m); js=0; len=c; pd=0; 28 memset(b,-1,sizeof(b)); memset(lon,0,sizeof(lon)); 29 memset(ma,-1,sizeof(ma)); memset(st,-1,sizeof(st)); 30 memset(mi,0x7f,sizeof(mi)); memset(stt,0x7f,sizeof(stt)); 31 for(int i=1;i<=m;++i) 32 33 int pp,xx; scanf("%d%d",&pp,&xx); 34 if(b[pp-1]==-1) b[pp-1]=xx; a[++js].p=pp-1; a[js].x=xx; 35 36 if(c==1) printf("1\\n"); continue; 37 sort(a+1,a+js+1,cmp); tail=a[js].p+c; 38 for(int i=1;i<=js;++i) 39 if(a[i].x<a[i-1].x) tail=a[i].p; break; 40 for(int i=0;i<len;++i) 41 if(b[i]!=-1) st[b[i]]=i; stt[b[i]]=min(stt[b[i]],i); 42 while(len<=tail) 43 44 if(b[len-1]!=-1) 45 st[b[len-1]]=len-1; stt[b[len-1]]=min(stt[b[len-1]],len-1); 46 for(int i=0;i<c;++i) mi[i]=stt[i]; ma[i]=st[i]; 47 mi[0]=0; mi[c-1]=min(len-1,mi[c-1]); ma[c-1]=len-1; chan.clear(); 48 int flag=0; 49 for(int i=1;i<=js;++i) 50 51 int ls=a[i].p%len; 52 if(b[ls]!=a[i].x) 53 54 if(b[ls]==-1) 55 56 if(a[i].x!=0&&ls<=ma[a[i].x-1]&&ma[a[i].x-1]!=-1) 57 flag=1; break; 58 if(ls>mi[a[i].x+1]) flag=1; break; 59 b[ls]=a[i].x; 60 chan.push_back(ls); 61 ma[a[i].x]=max(ma[a[i].x],ls); 62 mi[a[i].x]=min(mi[a[i].x],ls); 63 64 else flag=1; break; 65 66 67 if(flag) 68 69 for(int i=0;i<chan.size();++i) b[chan[i]]=-1; 70 len++; continue; 71 72 else 73 74 for(int i=0;i<c;++i) 75 76 if(ma[i]==-1) 77 78 if(i==0) ma[i]=0; mi[i]=0; 79 else 80 81 if(ma[i-1]+1!=mi[i+1]) ma[i]=ma[i-1]+1; mi[i]=ma[i]; 82 else flag=1; break; 83 84 85 if(mi[i]-ma[i-1]<=0&&i!=0) flag=1; break; 86 if(mi[i+1]-ma[i]==0&&i!=c-1) flag=1; break; 87 88 if(flag) 89 90 for(int i=0;i<chan.size();++i) b[chan[i]]=-1; 91 len++; continue; 92 93 lon[0]=ma[0]+1; 94 for(int i=1;i<c;++i) lon[i]=ma[i]-ma[i-1]; 95 pd=1; break; 96 97 98 if(!pd) printf("NO\\n"); continue; 99 for(int i=0;i<c;++i) printf("%d ",lon[i]); 100 puts(""); 101 102 return 0; 103
T2
是个非常zz的区间dp,我在考场上却没有想出来,暴搜还调了很久
如果dp转移的话,我们设$dp[i][j]$代表在$i$到$j$的区间中最多能得到的蛋糕大小。我们考虑怎么由$dp[i][j]$传到其他状态
首先对于这种成环的问题,很经典的一种处理方式就是延长一倍变成序列上的问题,对于转移,我们分为两种情况
1.卓司君取到蛋糕,那就是$i-1$和$j+1$都可以转移到,不出$2n$序列即可
2.雨咲(xiao四声)酱取到蛋糕,在保证$i-1$和$j+1$合法的情况下,选一个大的转移就可以了
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #define int long long 5 #define maxn 3010 6 using namespace std; 7 int n,ans; 8 int a[maxn*2]; 9 int dp[maxn*2][maxn*2]; 10 main() 11 12 scanf("%lld",&n); 13 for(int i=1;i<=n;++i) scanf("%lld",&a[i]); 14 a[0]=a[n]; 15 for(int i=1;i<=n;++i) a[i+n]=a[i]; 16 for(int i=1;i<=2*n;++i) dp[1][i]=a[i]; 17 for(int i=1;i<n;++i)//上一个区间长度 18 19 for(int j=1;j<=2*n;++j)//上一个区间左端点 20 21 int k=i+j-1;//上一个区间右端点 22 int l=j,r=k; 23 if(r>2*n) continue; 24 int ls1=l-1,ls2=r+1; 25 if(i%2)//上一个区间是奇数,不计算贡献的人选 26 27 if(ls1<0||ls2>2*n) continue; 28 int pos=0; 29 if(a[ls1]>a[ls2]) pos=ls1; 30 else pos=ls2; 31 if(pos>=l&&pos<=r) continue; 32 if(pos<0||pos>2*n) continue; 33 int ls=min(pos,l); 34 dp[i+1][ls]=max(dp[i+1][ls],dp[i][l]); 35 36 else//上一个区间是偶数,计算贡献的人选 37 38 if(ls1<l||ls1>r) 39 40 if(ls1<0||ls1>2*n) continue; 41 int ls=min(ls1,l); 42 dp[i+1][ls]=max(dp[i+1][ls],dp[i][l]+a[ls1]); 43 44 if(ls2<l||ls2>r) 45 46 if(ls2<0||ls2>2*n) continue; 47 int ls=min(ls2,l); 48 dp[i+1][ls]=max(dp[i+1][ls],dp[i][l]+a[ls2]); 49 50 51 52 53 for(int i=1;i<=2*n;++i) ans=max(ans,dp[n][i]); 54 printf("%lld\\n",ans); 55 return 0; 56
T3
说实话一开时没看懂题,说实话我最后抄的题解,觉得题解说的还可以,所以贴个题解,放个代码就跑了,我着急去水题
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<cmath> 5 #include<queue> 6 #define int long long 7 #define bh(i,j) ((i-1)*y+j) 8 #define maxn 6001000 9 #define maxm 6001000 10 using namespace std; 11 struct node 12 int pos,len; 13 bool operator <(const node &a)const 14 15 return len>a.len; 16 17 ; 18 struct NODE 19 int h,z; 20 ; 21 int x,y,a,b,c,n,ans,js,tot; 22 int xx[maxn],yy[maxn]; 23 int head[maxn],to[maxm],xia[maxm],w[maxm]; 24 int pd[maxn],dis[maxn]; 25 priority_queue <node> s; 26 queue <NODE> dl; 27 void add(int x,int y,int z) 28 29 to[++js]=y; xia[js]=head[x]; w[js]=z; head[x]=js; 30 31 main() 32 33 scanf("%lld%lld%lld%lld%lld%lld",&x,&y,&a,&b,&c,&n); x++; y++; tot=x*y; 34 for(int i=1;i<=n;++i) scanf("%lld%lld",&xx[i],&yy[i]); xx[i]++; yy[i]++; 35 memset(dis,0x7f,sizeof(dis)); 36 for(int i=1;i<=n;++i) 37 38 int ls=bh(xx[i],yy[i]); dis[ls]=0; 39 dl.push((NODE)xx[i],yy[i]); 40 41 while(dl.size()) 42 43 NODE ls=dl.front(); dl.pop(); 44 int ls1=ls.h,ls2=ls.z; 45 if(ls2-1>=1&&dis[bh(ls1,ls2-1)]>dis[bh(ls1,ls2)]+1) 46 47 dis[bh(ls1,ls2-1)]=dis[bh(ls1,ls2)]+1; 48 dl.push((NODE)ls1,ls2-1); 49 50 if(ls2+1<=y&&dis[bh(ls1,ls2+1)]>dis[bh(ls1,ls2)]+1) 51 52 dis[bh(ls1,ls2+1)]=dis[bh(ls1,ls2)]+1; 53 dl.push((NODE)ls1,ls2+1); 54 55 if(ls1-1>=1&&dis[bh(ls1-1,ls2)]>dis[bh(ls1,ls2)]+1) 56 57 dis[bh(ls1-1,ls2)]=dis[bh(ls1,ls2)]+1; 58 dl.push((NODE)ls1-1,ls2); 59 60 if(ls1+1<=x&&dis[bh(ls1+1,ls2)]>dis[bh(ls1,ls2)]+1) 61 62 dis[bh(ls1+1,ls2)]=dis[bh(ls1,ls2)]+1; 63 dl.push((NODE)ls1+1,ls2); 64 65 66 for(int i=1;i<=x;++i) 67 68 for(int j=1;j<=y;++j) 69 70 int ls1=bh(i,j),ls2=bh(i,j)+tot,ls3=bh(i,j)+2*tot; 71 if(i-1>=1) add(ls1,bh(i-1,j),a); 72 if(i+1<=x) add(ls1,bh(i+1,j),a); 73 if(j-1>=1) add(ls2,bh(i,j-1)+tot,a); 74 if(j+1<=y) add(ls2,bh(i,j+1)+tot,a); 75 add(ls3,ls1,b); add(ls3,ls2,b); 76 add(ls1,ls3,dis[ls1]*c); add(ls2,ls3,dis[ls1]*c); 77 if(i-1>=1) add(ls3,bh(i-1,j)+2*tot,c); 78 if(i+1<=x) add(ls3,bh(i+1,j)+2*tot,c); 79 if(j-1>=1) add(ls3,bh(i,j-1)+2*tot,c); 80 if(j+1<=y) add(ls3,bh(i,j+1)+2*tot,c); 81 82 83 memset(dis,0x7f,sizeof(dis)); 84 int qd=bh(xx[1],yy[1])+2*tot; 85 dis[qd]=0; s.push((node)qd,dis[qd]); 86 while(s.size()) 87 88 int qd=s.top().pos; s.pop(); 89 if(pd[qd]) continue; 90 pd[qd]=1; 91 for(int j=head[qd];j;j=xia[j]) 92 93 int ls=to[j]; 94 if(dis[ls]>dis[qd]+w[j]&&(!pd[ls])) 95 96 dis[ls]=dis[qd]+w[j]; 97 s.push((node)ls,dis[ls]); 98 99 100 101 int zd=bh(xx[n],yy[n]); ans=min(min(dis[zd],dis[zd+tot]),dis[zd+2*tot]); 102 printf("%lld\\n",ans); 103 return 0; 104
感谢这道题,把我从错误的堆优化dj的板子里拉出来
以上是关于9.3题解的主要内容,如果未能解决你的问题,请参考以下文章