比赛链接:https://codeforces.com/group/2g1PZcsgml/contest/338475
A,B,C,F,H,I,J,K;12;今天貌似比之前好了一点。
A
分析:
最长上升子序列。
代码如下:
#include<iostream> #include<cstring> using namespace std; int f[55][30]; char s[55]; int main() { scanf("%s",&s); int n=strlen(s); f[0][s[0]-'a']=1; for(int i=1;i<n;i++) { int c=s[i]-'a'; f[i][c]=1;// for(int j=0;j<26;j++)f[i][j]=max(f[i][j],f[i-1][j]); for(int j=0;j<c;j++)f[i][c]=max(f[i][c],f[i-1][j]+1); //printf("f[%d][%d]=%d\n",i,c,f[i][c]); } int mx=0; for(int k=0;k<26;k++)mx=max(mx,f[n-1][k]); printf("%d\n",26-mx); return 0; }me
B
分析:
BFS。
代码如下:
#include<iostream> #include<queue> #include<cstring> using namespace std; int const N=55; int n,m,len,dx[4],dy[4],stx,sty,edx,edy,ans,vis[N][N][N]; char s[N][N],op[N]; struct Nd{ int x,y,p,cnt; bool operator < (const Nd &a) const {return cnt>a.cnt;} }; priority_queue<Nd>q; void init() { dx[0]=0; dy[0]=-1; dx[1]=1; dy[1]=0; dx[2]=0; dy[2]=1; dx[3]=-1; dy[3]=0; for(int i=0;i<=n;i++) for(int j=0;j<m;j++) { if(s[i][j]=='R')stx=i,sty=j; if(s[i][j]=='E')edx=i,edy=j; } } bool can(int x,int y){if(x<0||x>=n||y<0||y>=m)return 0; return s[x][y]!='#';}//=='.'走不到'E'! int chg(char c){if(c=='L')return 0; if(c=='D')return 1; if(c=='R')return 2; if(c=='U')return 3;} void bfs() { memset(vis,0x3f3f3f3f,sizeof vis); q.push((Nd){stx,sty,0,0}); int nx,ny; while(q.size()) { Nd t=q.top(); q.pop(); if(t.x==edx&&t.y==edy){ans=t.cnt; break;} if(vis[t.x][t.y][t.p]<=t.cnt)continue; vis[t.x][t.y][t.p]=t.cnt; //printf("x=%d y=%d p=%d cnt=%d vis=%d\n",t.x,t.y,t.p,t.cnt,vis[t.x][t.y][t.p]); //bool fl=0; //if(t.x==0&&t.y==1&&t.p==2)fl=1,printf("!cnt=%d\n",t.cnt); for(int i=0;i<=3;i++){ if(can((nx=t.x+dx[i]),(ny=t.y+dy[i]))&&vis[nx][ny][t.p]>t.cnt+1) q.push((Nd){nx,ny,t.p,t.cnt+1}); //if(fl)printf("can(%d,%d)=%d vis=%d t.cnt+1=%d\n",nx,ny,can(nx,ny),vis[nx,ny,t.p],t.cnt+1); } //fl=0; if(t.p>=len)continue; q.push((Nd){t.x,t.y,t.p+1,t.cnt+1}); int dr=chg(op[t.p]); //if(t.x==1&&t.y==2&&t.p==3)fl=1,printf("!!cnt=%d\n",t.cnt); if(can((nx=t.x+dx[dr]),(ny=t.y+dy[dr]))){ q.push((Nd){nx,ny,t.p+1,t.cnt}); //if(fl)printf("nx=%d ny=%d\n",nx,ny); } else q.push((Nd){t.x,t.y,t.p+1,t.cnt}); } } int main() { scanf("%d%d",&n,&m); for(int i=0;i<n;i++)scanf("%s",&s[i]); scanf("%s",&op); len=strlen(op); init(); bfs(); printf("%d\n",ans); return 0; }me
C
分析:
过一遍即可。
代码如下:
#include<iostream> using namespace std; int const N=1e5+5; int n,k,len,a[N],ans; int main() { scanf("%d%d%d",&n,&k,&len); for(int i=1,p;i<=k;i++) scanf("%d",&p),a[p]=1; int num=0,l=1,r=len; for(int i=1;i<=len;i++)num+=a[i]; for(;r<=n;r++) { if(num==0)a[r]=1,a[r-1]=1,ans+=2,num=2; else if(num==1) { if(a[r])a[r-1]=1; else a[r]=1; ans++; num=2; } num-=a[l]; num+=a[r+1]; l++; } printf("%d\n",ans); return 0; }me
H
分析:
直接按右端点排序,DP。
注意离散化不要写错了!
代码如下:
#include<iostream> #include<algorithm> #define ll long long using namespace std; int const N=4e5+5; int n,cnt; ll R,tmp[N],f[N]; struct Nd{ ll l,r; }a[N]; bool cmp(Nd a,Nd b){return a.r<b.r;} int main() { scanf("%lld%d",&R,&n); for(int i=1;i<=n;i++) { scanf("%lld%lld",&a[i].l,&a[i].r); tmp[++cnt]=a[i].l; tmp[++cnt]=a[i].r; } sort(a+1,a+n+1,cmp); sort(tmp+1,tmp+cnt+1); cnt=unique(tmp+1,tmp+cnt+1)-tmp-1;///-1!!! for(int i=1;i<=n;i++) a[i].l=lower_bound(tmp+1,tmp+cnt+1,a[i].l)-tmp, a[i].r=lower_bound(tmp+1,tmp+cnt+1,a[i].r)-tmp; int p=1; for(int i=1;i<=cnt;i++) { f[i]=f[i-1]; while(p<=n&&a[p].r<=i)f[i]=max(f[i],f[a[p].l-1]-tmp[a[p].l]+tmp[a[p].r]+1),p++; //printf("i=%d tmp=%lld f=%lld\n",i,tmp[i],f[i]); } printf("%lld\n",R-f[cnt]); return 0; }me
I
分析:
贪心先放远处。
代码如下:
#include<iostream> #include<algorithm> #define ll long long using namespace std; int const N=1005; int n,k,ca,cb; ll ans; struct Nd{ int x,m; }a[N],b[N]; int ab(int x){return (x>0)?x:-x;} bool cmp(Nd aa,Nd bb){return ab(aa.x)<ab(bb.x);} void work1() { for(int i=ca;i;i--) { if(a[i].m==0)continue; if(a[i].m>=k)ans+=(ll)a[i].x*(a[i].m/k)*2,a[i].m%=k; if(a[i].m==0)continue; ans+=(ll)a[i].x*2; int res=k-a[i].m,p=i-1; a[i].m=0; while(p&&res) { if(res>a[p].m)res-=a[p].m,a[p].m=0,p--; else a[p].m-=res,res=0; } } } void work2() { for(int i=cb;i;i--) { if(b[i].m==0)continue; if(b[i].m>=k)ans+=(ll)(-b[i].x)*(b[i].m/k)*2,b[i].m%=k; if(b[i].m==0)continue; ans+=(ll)(-b[i].x)*2; //printf("a[%d].x=%d m=%d ans=%lld\n",i,a[i].x,a[i].m,ans); int res=k-b[i].m,p=i-1; b[i].m=0; while(p&&res) { if(res>b[p].m)res-=b[p].m,b[p].m=0,p--; else b[p].m-=res,res=0; } } } int main() { scanf("%d%d",&n,&k); for(int i=1,xx,mm;i<=n;i++) { scanf("%d%d",&xx,&mm); if(xx>=0)a[++ca].x=xx,a[ca].m=mm; else b[++cb].x=xx,b[cb].m=mm; } sort(a+1,a+ca+1,cmp); sort(b+1,b+cb+1,cmp); work1(); work2(); printf("%lld\n",ans); return 0; } /* 4 10 -7 5 -2 3 5 7 9 5 *//* 7 1 9400000 10000000 9500000 10000000 9600000 10000000 9700000 10000000 9800000 10000000 9900000 10000000 10000000 10000000 */me
J
分析:
一个数\( v \)最多会被\( mod log(v) \)次,所以问题是怎么快速找到下一个比它小的数;
可以用线段树或ST表做,都是\( log(n) \)的。
代码如下:
#include<iostream> #define ll long long #define mid ((l+r)>>1) #define ls (u<<1) #define rs ((u<<1)|1) using namespace std; int const N=2e5+5; int n,q,tr[N<<2]; ll a[N],v; void upt(int u) { if(a[tr[ls]]<=a[tr[rs]])tr[u]=tr[ls]; else tr[u]=tr[rs]; } void build(int u,int l,int r) { if(l==r){tr[u]=l; return;} build(ls,l,mid); build(rs,mid+1,r); upt(u); } ll qry(int u,int l,int r,int ql,int qr) { ll ret=0; if(l==r)return a[l]<=v?l:0; if(l>=ql&&r<=qr) { if(a[tr[ls]]<=v)return qry(ls,l,mid,ql,qr); else if(a[tr[rs]]<=v)return qry(rs,mid+1,r,ql,qr); else return 0; } if(mid>=ql)ret=qry(ls,l,mid,ql,qr); if(ret)return ret; if(mid<qr)ret=qry(rs,mid+1,r,ql,qr); return ret; } int main() { scanf("%d%d",&n,&q); for(int i=1;i<=n;i++)scanf("%lld",&a[i]); build(1,1,n); for(int i=1,ql,qr;i<=q;i++) { scanf("%lld%d%d",&v,&ql,&qr); while(ql<=qr) { int ps=qry(1,1,n,ql,qr); if(!ps)break; v%=a[ps]; ql=ps+1; //printf("ps=%d\n",ps); } printf("%lld\n",v); } return 0; }me
K
分析:
\( f[i] \) 表示至少赢 \( i \) 次的方案数;
\( f[i] = C_{2^k-r}^{2^i-1} / C_{2^k-1}^{2^i-1} \);
直接\( k*2^r \)做会TLE,但是复杂度应该是\( 2*10^7 \)才对,不知为什么;
所以需要利用上一次的答案,每次转移\( O(2^{i-1}) \),就能过了。
代码如下:
#include<iostream> #include<cmath> #define db double using namespace std; int const N=(1<<20)+5; db const eps=1e-6; int k,r; db f[25],ans; int main() { scanf("%d%d",&k,&r); f[0]=1; for(int i=1;i<=k;i++) { if((1<<i)-1>(1<<k)-r)break; //f[i]=1; int L=(1<<k)-(1<<i)-r+2,L2=(1<<k)-r+1,R=(1<<k)-(1<<i),R2=(1<<k)-1; //for(int j=L,j2=L2;j<=R;j++,j2++)f[i]*=j,f[i]/=j2; f[i]=f[i-1]; int A=(1<<k)-r-(1<<i)+1,B=(1<<k)-(1<<i); for(int j=1;j<=(1<<(i-1));j++)f[i]*=(A+j),f[i]/=(B+j); } for(int i=1;i<=k;i++)ans+=(f[i]-f[i+1])*i; printf("%.5lf\n",ans); return 0; }me