9.3题解

佐手、 提交于 2020-03-14 12:17:48

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 }
调试过程中hack掉无数AC代码的来之不易的代码

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 }
View Code

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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!