想起一句話ios
課上求生存,課下求發展ide
發展還好說,如何生存?優化
生存很困難。。。ui
沒什麼可抱怨的。有AK的。高分的也不少。spa
該說的在《Dust》裏說完了,安靜會吧。3d
這場rank43怎麼追?code
最大240分差,可能這一輪就完蛋了。blog
知道有多緊迫了嗎?字符串
上次爆個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 }
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 }
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 }