想起一句话
课上求生存,课下求发展
发展还好说,如何生存?
生存很困难。。。
没什么可抱怨的。有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 }
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 }
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 }