• [考试反思]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
    ",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
    ",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
    ",ans);
    35 }
    View Code
  • 相关阅读:
    SDN实验2:Mininet 实验——拓扑的命令脚本生成
    2020软工实践第一次作业
    POJ2942-Knights of the Round Table
    POJ1966 ZOJ2182<无向图点连通度 Isap版>
    POJ1523(求割点)
    POJ2391(最大流Isap+Floyd+二分)
    POJ1087 ZOJ1157(最大流Isap+map映射)
    POJ1459(最大流Isap)
    数字的字符串处理 (转)
    POJ2112 最大流(Isap+Floyd+二分)
  • 原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/11742420.html
Copyright © 2020-2023  润新知