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的板子里拉出来
来源:https://www.cnblogs.com/hzjuruo/p/11518799.html
