week3做題記錄
阿新 • • 發佈:2020-10-21
A棧,純模擬。
1 #include<cstdio> 2 #include<cmath> 3 #include<algorithm> 4 #include<cstring> 5 using namespace std; 6 char s1[200000],s2[200000]; 7 int sta[200000],ans[200000]; 8 int main() 9 { 10 int n,len=0; 11 while (~scanf("%d ",&n)) 12 { 13 for (int i=1;i<=len;i++) sta[i]=0; 14 scanf("%[^ ]",s1+1); 15 scanf("%s",s2+1); 16 int i=1,j=1,p=0,len=0; 17 while (i<=n||j<=n) 18 { 19 while (sta[len]!=s2[j]-'0'&&i<=n) 20 { 21 p++; 22 ans[p]=1; 23 len++; 24sta[len]=s1[i]-'0'; 25 i++; 26 } 27 if (sta[len]!=s2[j]-'0') break; 28 p++; 29 ans[p]=0; 30 len--; 31 j++; 32 } 33 if (p==2*n) 34 { 35 printf("Yes.\n"); 36 for(int i=1;i<=p;i++) if (ans[i]) printf("in\n");else printf("out\n"); 37 }else printf("No.\n"); 38 printf("FINISH\n"); 39 } 40 }
B連結串列,純模擬。
1 #include<cstdio> 2 #include<cmath> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 int pre[100000],nex[100000]; 7 int main() 8 { 9 int n; 10 scanf("%d",&n); 11 while (n) 12 { 13 n--; 14 int m; 15 scanf("%d",&m); 16 for (int i=1;i<m;i++) nex[i]=i+1; 17 for (int i=2;i<=m;i++) pre[i]=i-1; 18 nex[m]=0; 19 int head=1,w=1; 20 while (m>3) 21 { 22 if (w) 23 { 24 for (int i=head,j=1;i;j++,i=nex[i]) if (j%2==0) 25 { 26 pre[nex[i]]=pre[i]; 27 nex[pre[i]]=nex[i]; 28 m--; 29 //if (m<=3) break; 30 } 31 w=1-w; 32 }else 33 { 34 for (int i=head,j=1;i;j++,i=nex[i]) if (j%3==0) 35 { 36 pre[nex[i]]=pre[i]; 37 nex[pre[i]]=nex[i]; 38 m--; 39 //if (m<=3) break; 40 } 41 w=1-w; 42 } 43 } 44 for (int i=head;i;i=nex[i]) if (nex[i]==0) printf("%d",i);else printf("%d ",i); 45 printf("\n"); 46 } 47 }
C棧,寫計算器,這裡用棧處理,加號和減號忽略,先計算乘法和除法,最後在遍歷一遍棧即可。
程式碼寫差了,其實可以寫得更簡短。
1 #include<cstdio> 2 #include<cmath> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 int main() 7 { 8 char s[500],sta[1000]; 9 double ss[1000]; 10 while (~scanf("%[^\n]",s+1)) 11 { 12 scanf("\n"); 13 if (strlen(s+1)==1&&s[1]=='0') break; 14 int n=strlen(s+1),len=0; 15 s[n+1]=' '; 16 n++; 17 int last=1; 18 for (int i=1;i<=n;i++) 19 { 20 if (s[i]==' ') 21 { 22 if (i-last==1) 23 { 24 if (s[i-1]=='+'||s[i-1]=='-'||s[i-1]=='*'||s[i-1]=='/') 25 { 26 len++; 27 sta[len]=s[i-1]; 28 }else 29 { 30 if (sta[len]=='*') 31 { 32 len--; 33 ss[len]=ss[len]*(double)(s[i-1]-'0'); 34 }else if (sta[len]=='/') 35 { 36 len--; 37 ss[len]=ss[len]/(double)(s[i-1]-'0'); 38 }else 39 { 40 len++; 41 sta[len]='&'; 42 ss[len]=(double)(s[i-1]-'0'); 43 } 44 } 45 }else 46 { 47 48 double py=0; 49 for (int j=last;j<i;j++) py=py*10.00+(double)(s[j]-'0'); 50 if (sta[len]=='*') 51 { 52 len--; 53 ss[len]=ss[len]*(double)py; 54 }else if (sta[len]=='/') 55 { 56 len--; 57 ss[len]=ss[len]/(double)py; 58 }else 59 { 60 len++; 61 sta[len]='&'; 62 ss[len]=(double)py; 63 } 64 } 65 last=i+1; 66 } 67 } 68 double ans=ss[1]; 69 for (int i=3;i<=len;i++) 70 { 71 if (sta[i]=='&') 72 { 73 if (sta[i-1]=='+') ans=ans+ss[i];else ans=ans-ss[i]; 74 } 75 } 76 printf("%.2lf\n",ans); 77 } 78 }
D棧,實際上並沒有用到棧或者佇列就解決了問題。
其實可以發現一些簡單的數學規律,因此得到了一個O(n)的做法。
1 #include<cstdio> 2 #include<cmath> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 char s[10000],s1[10000]; 7 int a[1000],b[1000],c[1000],py[1000],se[1000]; 8 int main() 9 { 10 int n,tt=0; 11 while (1) 12 { 13 tt++; 14 scanf("%d",&n); 15 if (!n) break; 16 scanf("%s",s+1); 17 scanf("%s",s1+1); 18 int l=0,r=0; 19 for (int i=1;i<n-1;i++) if (s1[i]=='R') r++;else l++; 20 int j=r+1; 21 if (r%2==0) 22 { 23 for (int i=n-r;i<=n;i=i+2,j--) a[j]=i; 24 for (int i=n-1;j;j--,i=i-2) a[j]=i; 25 }else 26 { 27 for (int i=n-r;i<=n;i=i+2,j--) a[j]=i; 28 for (int i=n;j;j--,i=i-2) a[j]=i; 29 } 30 //l++; 31 if (l&1) 32 { 33 int j=1; 34 for (int i=l;i>=1;i=i-2,j++) b[j]=i; 35 for (int i=2;j<=l+1;j++,i=i+2) b[j]=i; 36 }else 37 { 38 int j=1; 39 for (int i=l;i>=2;i=i-2,j++) b[j]=i; 40 for (int i=1;j<=l+1;j++,i=i+2) b[j]=i; 41 } 42 if (s1[n-1]=='R') 43 { 44 int j=1; 45 for (int i=r+1;i>=1;i--,j++) c[j]=a[i]; 46 for (int i=1;i<=l+1;i++,j++) c[j]=b[i]; 47 //r++; 48 }else 49 { 50 int j=1; 51 for (int i=l+1;i>=1;i--,j++) c[j]=b[i]; 52 for (int i=1;i<=r+1;i++,j++) c[j]=a[i]; 53 //l++; 54 } 55 for (int i=1;i<=l+1;i++) 56 { 57 if (l%2==0) 58 { 59 if (i&1) py[i]=0;else py[i]=1; 60 }else 61 { 62 if (i&1) py[i]=1;else py[i]=0; 63 } 64 } 65 for (int i=n,j=1;i>=n-r;i--,j++) 66 { 67 if (r%2==0) 68 { 69 if (j&1) py[i]=0;else py[i]=1; 70 }else 71 { 72 if (j&1) py[i]=1;else py[i]=0; 73 } 74 } 75 if (s1[n-1]=='R') for (int i=n;i>=n-r;i--) py[i]=1-py[i]; 76 else for (int i=1;i<=l+1;i++) py[i]=1-py[i]; 77 for (int i=1;i<=n;i++) if (s[i]=='U') se[i]=1;else se[i]=0; 78 for (int i=1;i<=n;i++) if (py[i]) se[i]=1-se[i]; 79 int m; 80 scanf("%d",&m); 81 printf("Pile %d\n",tt); 82 for (int i=1;i<=m;i++) 83 { 84 int x; 85 scanf("%d",&x); 86 printf("Card %d is a face",x); 87 if (se[c[x]]) printf(" up %d.\n",c[x]); 88 else printf(" down %d.\n",c[x]); 89 } 90 } 91 }
E佇列。實際上是佇列中的佇列...一開始看錯資料範圍,以為能暴力,後來加了一點點小小的優化。
#include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; const int N=2e6+10; int pre[N],nex[N],v[N],vv[N],cc[N]; int main() { //freopen("test.in","r",stdin); int n,tt=0; while (1) { scanf("%d",&n); if (!n) break; printf("Scenario #%d\n",++tt); for (int i=1;i<=n;i++) { int m; scanf("%d",&m); for (int j=1;j<=m;j++) { int x; scanf("%d",&x); v[x]=i; } } for (int i=1;i<=n;i++) vv[i]=-1,cc[i]=0; scanf("\n"); char s[10000]; int he=0,ta=0; while (1) { scanf("%[^\n]",s+1); scanf("\n"); if (s[1]=='S') { printf("\n"); break; } int le=strlen(s+1); int w=0; for (int i=1;i<=le;i++) if (s[i]>='0'&&s[i]<='9') w=w*10+s[i]-'0'; if (s[1]=='E') { if (!he) { he=w; ta=w; pre[he]=0; nex[he]=0; vv[v[w]]=he; cc[v[w]]=1; }else { int last=vv[v[w]]; //for (int i=he;i;i=nex[i]) if (v[i]==v[w]) last=i; if (last==-1||last==ta) nex[ta]=w,pre[w]=ta,ta=w,nex[w]=0;else pre[nex[last]]=w,nex[w]=nex[last],nex[last]=w,pre[w]=last; vv[v[w]]=w; cc[v[w]]++; } }else { printf("%d\n",he); cc[v[he]]--; if (!cc[v[he]]) vv[v[he]]=-1; he=nex[he]; pre[he]=0; } } } }
F,單調佇列裸題,只不過需要預處理時間。
1 #include<cstdio> 2 #include<cmath> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 int f[15]; 7 int d[200000],q[200000],vp[200000]; 8 int pd(int x) 9 { 10 if ((x%4==0&&x%400!=0)||x%100==0) return 1; 11 return 0; 12 } 13 int main() 14 { 15 //freopen("test.in","r",stdin); 16 int n,m; 17 f[1]=31;f[2]=28;f[3]=31;f[4]=30;f[5]=31;f[6]=30;f[7]=31; 18 f[8]=31;f[9]=30;f[10]=31;f[11]=30;f[12]=31; 19 while (1) 20 { 21 scanf("%d%d",&n,&m); 22 if (!n&&!m) break; 23 for (int i=1;i<=m;i++) vp[i]=0; 24 for (int i=1;i<=n;i++) 25 { 26 char s[5]; 27 scanf("%s",s+1); 28 int y; 29 if (s[1]=='J'&&s[2]=='a') y=1; 30 if (s[1]=='F') y=2; 31 if (s[1]=='M'&&s[3]=='r') y=3; 32 if (s[1]=='A'&&s[3]=='r') y=4; 33 if (s[1]=='M'&&s[3]=='y') y=5; 34 if (s[1]=='J'&&s[3]=='n'&&s[2]=='u') y=6; 35 if (s[1]=='J'&&s[3]=='l') y=7; 36 if (s[1]=='A'&&s[2]=='u') y=8; 37 if (s[1]=='S') y=9; 38 if (s[1]=='O') y=10; 39 if (s[1]=='N') y=11; 40 if (s[1]=='D') y=12; 41 int t,nn,xs,x; 42 scanf("%d%d%d%d",&t,&nn,&xs,&x); 43 int tmp=xs+1; 44 tmp=tmp+(t-1)*24; 45 for (int j=y-1;j>=1;j--) if (j==2&&pd(nn)) tmp=tmp+29*24;else tmp=tmp+24*f[j]; 46 for (int j=2000;j<nn;j++) if (pd(j)) tmp=tmp+366*24;else tmp=tmp+365*24; 47 vp[tmp]+=x; 48 } 49 long long ans=0; 50 int he=1,ta=0; 51 int ss,tt; 52 scanf("%d%d",&tt,&ss); 53 for (int i=1;i<=m;i++) 54 { 55 int x; 56 scanf("%d",&x); 57 while (ta>=he&&d[ta]-q[ta]*ss>=x-i*ss) ta--; 58 ta++; 59 d[ta]=x; 60 q[ta]=i; 61 while (q[ta]-q[he]>tt) he++; 62 if (vp[i]) ans=ans+1ll*d[he]*vp[i]+1ll*(i-q[he])*ss*vp[i]; 63 } 64 printf("%I64d\n",ans); 65 } 66 }
G單調佇列裸題+1,只不過我寫了O(nlogn)的二分+rmq,感覺這個方法細節少一點(?),畢竟不是很擅長寫單調佇列。
1 #include<cstdio> 2 #include<cmath> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int N=1e5+10; 7 int e[N],a[N][20],n; 8 int query(int l,int r) 9 { 10 int lg=e[r-l+1]; 11 return min(a[l][lg],a[r-(1<<lg)+1][lg]); 12 } 13 int efl(int x) 14 { 15 int l=1,r=x; 16 int ret=x; 17 while (l<=r) 18 { 19 int mid=l+r>>1; 20 if (query(mid,x)>=a[x][0]) 21 { 22 ret=mid; 23 r=mid-1; 24 }else l=mid+1; 25 } 26 return ret; 27 } 28 int efr(int x) 29 { 30 int l=x,r=n; 31 int ret=x; 32 while (l<=r) 33 { 34 int mid=l+r>>1; 35 if (query(x,mid)>=a[x][0]) 36 { 37 ret=mid; 38 l=mid+1; 39 }else r=mid-1; 40 } 41 return ret; 42 } 43 int main() 44 { 45 for (int i=2;i<=100000;i++) e[i]=e[i>>1]+1; 46 while (1) 47 { 48 scanf("%d",&n); 49 if (!n) break; 50 for (int i=1;i<=n;i++) scanf("%d",&a[i][0]); 51 for (int j=1;j<=17;j++) for (int i=1;i+(1<<j)-1<=n;i++) a[i][j]=min(a[i][j-1],a[i+(1<<j-1)][j-1]); 52 long long ans=0; 53 for (int i=1;i<=n;i++) 54 { 55 int x=efl(i),y=efr(i); 56 ans=max(ans,1ll*(y-x+1)*a[i][0]); 57 } 58 printf("%lld\n",ans); 59 } 60 }
H最大權閉合子圖,用網路流解決。
建圖是這樣的,正權點與源點連流量為權值的邊,負權點與源點連流量為絕對值的邊,如果x有指向y的邊,那麼y向x連無限流量的邊。
答案就是原來正權和減去最大流。
跑完網路流之後,可以得到一個最小割。
1 #include<cstdio> 2 #include<cmath> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int inf=0x3f3f3f3f; 7 const int N=1e6+10; 8 int tot=1,cur[N],he[N],t[N],cc[N],ne[N],cnt[N],d[N],n; 9 void link(int x,int y,int z) 10 { 11 tot++; 12 ne[tot]=he[x]; 13 he[x]=tot; 14 t[tot]=y; 15 cc[tot]=z; 16 tot++; 17 ne[tot]=he[y]; 18 he[y]=tot; 19 t[tot]=x; 20 cc[tot]=0; 21 } 22 int flow(int x,int y) 23 { 24 if (x==n+2) return y; 25 int cost=0,i=cur[x]; 26 while (i) 27 { 28 cur[x]=i; 29 if (cc[i]&&d[t[i]]+1==d[x]) 30 { 31 int ret=flow(t[i],min(y-cost,cc[i])); 32 cost=cost+ret; 33 cc[i]=cc[i]-ret; 34 cc[i^1]=cc[i^1]+ret; 35 if (y==cost||d[n+1]>n+2) return cost; 36 } 37 i=ne[i]; 38 } 39 cur[x]=he[x]; 40 if (cnt[d[x]]==1) d[n+1]=n+3; 41 cnt[d[x]]--; 42 cnt[d[x]+1]++; 43 d[x]++; 44 return cost; 45 } 46 int main() 47 { 48 int m; 49 while (~scanf("%d%d",&n,&m)) 50 { 51 long long tmp=0; 52 for (int i=1;i<=n;i++) 53 { 54 int x; 55 scanf("%d",&x); 56 if (x>=0) tmp=tmp+x,link(n+1,i,x);else link(i,n+2,-x); 57 } 58 for (int i=1;i<=m;i++) 59 { 60 int x,y; 61 scanf("%d%d",&x,&y); 62 link(x,y,inf); 63 } 64 cnt[0]=n+2; 65 while (d[n+1]<=n+2) tmp=tmp-flow(n+1,inf); 66 printf("%I64d\n",tmp); 67 for (int i=1;i<=n+2;i++) he[i]=0,d[i]=0,cur[i]=0; 68 tot=1; 69 } 70 }