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的板子里拉出来