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 
调试过程中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的板子里拉出来

以上是关于9.3题解的主要内容,如果未能解决你的问题,请参考以下文章

正睿2018暑假集训 比赛题选做

双周赛 52,单周赛 241 题解

精LintCode领扣算法问题答案:入门

题解目录

[题解]noip杂题题解

BZOJ1798题解 Seq维护序列题解 双tag裸线段树