[考试反思]1025csp-s模拟测试87:生存

想起一句话

课上求生存,课下求发展

发展还好说,如何生存?

生存很困难。。。

没什么可抱怨的。有AK的。高分的也很多。

该说的在《Dust》里说完了,安静会吧。

这场rank43怎么追?

最大240分差,可能这一轮就完蛋了。

知道有多紧迫了吗?

上次爆个0导致追不回来直接滚出第一机房依旧令我印象深刻。

OI不会给你任何一次失手的机会。CSP-S也只有6道题。

这一天下来分数上限就是360了?

再说这样的话Day2还能稳住心态吗?

省一可能都拿不到吧?

不要轻视任何一道题与任意一次考试,希望不要在CSP上付出代价。

时间分配也有一点问题,难易度判断又挂了。

 

T1:maze

注意,OI坐标系横着是y轴竖着是x轴,与数学坐标系不同。

样例又是精心构造的。

爆零快乐。

二分+最短路,没什么好说的。

 1 #include<cstdio>
 2 #include<queue>
 3 using namespace std;
 4 struct P{int x,y;double d;friend bool operator<(P a,P b){return a.d>b.d;}};
 5 priority_queue<P>q;
 6 #define tx x+xx[i]
 7 #define ty y+yy[i]
 8 const int yy[]={0,0,1,-1};
 9 const int xx[]={1,-1,0,0};
10 int n,m,can[101][101],sx,sy,ex,ey;double s,dt[101][101];
11 bool chk(double k){
12     for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)dt[i][j]=1e16;
13     dt[sx][sy]=0;
14     q.push((P){sx,sy,0});
15     while(!q.empty()){
16         int x=q.top().x,y=q.top().y;double d=q.top().d;q.pop();
17         if(d-dt[x][y]>1e-4)continue;
18         for(int i=0;i<=1;++i)if(can[tx][ty]&&dt[tx][ty]>d+k)
19             q.push((P){tx,ty,dt[tx][ty]=d+k});
20         for(int i=2;i<=3;++i)if(can[tx][ty]&&dt[tx][ty]>d+1)
21             q.push((P){tx,ty,dt[tx][ty]=d+1});
22     }
23     return dt[ex][ey]<s;
24 }
25 int main(){
26     scanf("%d%d%d%d%d%d",&n,&m,&sx,&sy,&ex,&ey);
27     for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) scanf("%d",&can[i][j]), can[i][j]^=1;
28     scanf("%lf",&s);
29     double l=0,r=100000;
30     while(r-l>1e-4)if(chk((l+r)/2))l=(l+r)/2;else r=(l+r)/2;
31     printf("%.3lf\n",l);
32 }
View Code

 

T2:bird

考场上就能看出来是个朴素的线段树优化dp。

但是分配时间不够,没细想。

因为一只鸟不能被打两遍,所以用线段树上的加减“篡改”一下转移值。

全场倒数第4个改出来。状态极差,效率极低。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<vector>
 4 using namespace std;
 5 vector<int>v1[500005],v2[500005];
 6 int mx[8000005],cl[8000005],cr[8000005],lz[8000005],n,ans,k,l,r,cf[500005];
 7 void build(int p,int l,int r){
 8     cl[p]=l;cr[p]=r;
 9     if(l==r)return;
10     build(p<<1,l,l+r>>1);build(p<<1|1,(l+r>>1)+1,r);
11 }
12 void down(int p){
13     mx[p<<1]+=lz[p];mx[p<<1|1]+=lz[p];
14     lz[p<<1]+=lz[p];lz[p<<1|1]+=lz[p];
15     lz[p]=0;
16 }
17 int ask(int p,int l,int r){if(r<l)return 0;
18     if(l<=cl[p]&&cr[p]<=r)return mx[p];
19     if(lz[p])down(p);
20     return max(l<=cr[p<<1]?ask(p<<1,l,r):0,r>=cl[p<<1|1]?ask(p<<1|1,l,r):0);
21 }
22 void add(int p,int l,int r,int w){
23     if(l<=cl[p]&&cr[p]<=r){mx[p]+=w;lz[p]+=w;return;}
24     if(lz[p])down(p);
25     if(l<=cr[p<<1])add(p<<1,l,r,w);
26     if(r>=cl[p<<1|1])add(p<<1|1,l,r,w);
27     mx[p]=max(mx[p<<1],mx[p<<1|1]);
28 }
29 int main(){
30     build(1,0,500000);
31     scanf("%d%d",&n,&k);
32     while(n--){
33         scanf("%d%d",&l,&r);
34         l=max(l,0);
35         if(r<0)continue;
36         v1[l].push_back(r),v2[r].push_back(l);
37         cf[l]++;cf[r+1]--;
38     }int cnt=0;
39     for(int i=0;i<=500000;++i){
40         if(i)cf[i]+=cf[i-1];
41         for(int j=0;j<v1[i].size();++j)add(1,i,v1[i][j],-1);
42         int x=ask(1,0,i-k)+cf[i];
43         add(1,i,i,x);ans=max(ans,x);
44         for(int j=0;j<v2[i].size();++j)add(1,v2[i][j],i,+1);
45     }printf("%d\n",ans);
46 }
View Code

 

T3:stone

第二天早上改题,状态回升。

显然可以打表,考场上也打出了dp。然后没有找到规律。

表太小了看不出来,其实打表得到的1是联通的,中间凭空出现了几个零散的0。

出现0的条件是a[i]=b[j-1]&&a[i-1]=b[j]&&a[i]!=a[i-1]

证明skyh说的挺好的,我太菜不写了

然后用子序列dp干一下处理出每一行的左右端点,再挖去0。

因为只有3种字符,所以手动讨论一下相邻两位的字符,用前缀和统计一下每个字符串在b里出现的次数,在a的lr之间求出即可。

 1 #include<cstdio>
 2 #include<iostream>
 3 using namespace std;
 4 char a[1000005],b[1000005];int n,m,l[1000005],r[1000005];long long ans;
 5 int ab[1000005],ac[1000005],ba[1000005],bc[1000005],ca[1000005],cb[1000005];
 6 int main(){
 7     scanf("%s%s",a+1,b+1);
 8     while(a[n+1])n++;
 9     while(b[m+1])m++;
10     int p1=1,p2=1;
11     for(int i=1;i<=n;++i)if(a[i]==b[p1])l[i]=p1++;else l[i]=p1;
12     for(int i=1;i<=m;++i)if(b[i]==a[p2])p2++,r[p2]=min(i+1,m);else r[p2]=min(i+1,m);
13     if(!r[1])r[1]=1;
14     for(int i=1;i<=n;++i)if(!r[i])r[i]=m;
15     for(int i=2;i<=m;++i){
16              if(b[i]=='A'&&b[i-1]=='C')ac[i]++;
17         else if(b[i]=='A'&&b[i-1]=='B')ab[i]++;
18         else if(b[i]=='B'&&b[i-1]=='A')ba[i]++;
19         else if(b[i]=='B'&&b[i-1]=='C')bc[i]++;
20         else if(b[i]=='C'&&b[i-1]=='A')ca[i]++;
21         else if(b[i]=='C'&&b[i-1]=='B')cb[i]++;
22         ac[i]+=ac[i-1];ab[i]+=ab[i-1];
23         bc[i]+=bc[i-1];ba[i]+=ba[i-1];
24         ca[i]+=ca[i-1];cb[i]+=cb[i-1];
25     }
26     for(int i=1;i<=n;++i)ans+=r[i]-l[i]+1;
27     for(int i=2;i<=n;++i)
28              if(a[i]=='A'&&a[i-1]=='C')ans-=ca[r[i]]-ca[l[i]-1];
29         else if(a[i]=='A'&&a[i-1]=='B')ans-=ba[r[i]]-ba[l[i]-1];
30         else if(a[i]=='B'&&a[i-1]=='A')ans-=ab[r[i]]-ab[l[i]-1];
31         else if(a[i]=='B'&&a[i-1]=='C')ans-=cb[r[i]]-cb[l[i]-1];
32         else if(a[i]=='C'&&a[i-1]=='A')ans-=ac[r[i]]-ac[l[i]-1];
33         else if(a[i]=='C'&&a[i-1]=='B')ans-=bc[r[i]]-bc[l[i]-1];
34     printf("%lld\n",ans);
35 }
View Code

 

posted @ 2019-10-26 11:59  DeepinC  阅读(224)  评论(0编辑  收藏  举报