[20180528]校内模拟赛
T1:AtCoder 2069
很简单的最短路呀,可是好像很多同学WA了很多次。
#include<bits/stdc++.h> using namespace std; inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return x*f; } #define MN 100005 #define inf 200000000 int n,m,d[MN]; struct edge{ int to,c,nex; }e[MN*4];int hr[MN],cnt; inline void ins(int f,int t,int c){ e[++cnt]=(edge){t,c,hr[f]};hr[f]=cnt; } int q[MN*40],top; bool inq[MN]; set<int> col[MN]; inline void sp(){ register int i,j; for(i=1;i<=n;i++) d[i]=inf; inq[1]=1; for(d[q[top=i=1]=1]=0;i<=top;inq[q[i++]]=false) for(j=hr[q[i]];j;j=e[j].nex){ bool t=col[q[i]].find(e[j].c)==col[q[i]].end(); if(d[e[j].to]>d[q[i]]+t){ if(!inq[e[j].to]) inq[e[j].to]=1,q[++top]=e[j].to; col[e[j].to].clear(),col[e[j].to].insert(e[j].c); d[e[j].to]=d[q[i]]+t; } else if(d[e[j].to]==d[q[i]]+t&&col[e[j].to].find(e[j].c)==col[e[j].to].end()){ if(!inq[e[j].to]) inq[e[j].to]=1,q[++top]=e[j].to; col[e[j].to].insert(e[j].c); } } } int main(){ n=read(),m=read(); register int i,a,b,c; for(i=1;i<=m;i++) a=read(),b=read(),c=read(),ins(a,b,c),ins(b,a,c); sp();printf(d[n]==inf?"-1":"%d\n",d[n]); return 0; }
T2:Atcoder 2656
人生第一次做交互题,很有思路的样子?但是就是WA了很多次,至今也不知道之前到底错在哪了,只好照着学长讲的又打了一遍。
#include<bits/stdc++.h> using namespace std; inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return x*f; } #define mid (l+r>>1) int a[15],dig; char c[14]; long long ans,digi[15]; bool check(long long x){ printf("? %lld\n",x); fflush(stdout); scanf("%s",c); if(c[0]=='Y') return 1; return 0; } main(){ digi[0]=1;dig=1; for(int i=1;i<=9;i++){ digi[i]=digi[i-1]*10; printf("? %lld\n",digi[i]); fflush(stdout); scanf("%s",c); if(c[0]=='N') break; dig++; } if(dig==10){ int len; for(len=0;len<9;++len){ printf("? %lld\n",digi[len+1]-1); fflush(stdout); scanf("%s",c); if(c[0]=='Y') break; } printf("! %lld\n",digi[len]); fflush(stdout);return 0; } for(int i=1;i<=dig;++i){ int l=i==1,r=9; while(l<r){ if(check((ans+mid*digi[dig-i])*10+digi[dig-i+1]-1)) r=mid; else l=mid+1; } ans+=l*digi[dig-i]; } printf("! %lld\n",ans); fflush(stdout); return 0; }
T3:Atcoder 3673
首先f[i]表示填到第i这个位置,最少的Hamming distanc,然后很简单转移一下吧。(num是0的前缀数组)
1.f[i]=min(f[i],f[i-1]+a[i]) 无所作为
2.f[v[i][j]]=min(f[v[i][j]],f[i]+num[v[i][j]]-num[i],query(i,v[i][j])+num[v[i][j]])
表示填了这个区间 不填,找到和【i,v[i][j]】相交的区间,找到最优的转移方法(可以用线段树查区间最小,存f[i]-num[i]的值)
好像也不难的样子,可是太弱了,好久才听懂。
#include<iostream> #include<cstring> #include<cstdio> #include<vector> using namespace std; inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return x*f; } #define MN 200005 #define N 262144 int n,m,num[MN],f[MN],t[N*2+5],a[MN]; vector<int> v[MN]; inline void rw(int x,int v){for(x+=N+1;t[x]=min(t[x],v),x>>=1;);} inline int query(int l,int r){ int res=1e9; for(l+=N,r+=N+2;l^r^1;l>>=1,r>>=1){ if(~l&1) res=min(res,t[l+1]); if( r&1) res=min(res,t[r-1]); } return res; } int main(){ n=read();register int i,j; for(i=1;i<=n;++i) num[i]=num[i-1]+1-(a[i]=read()),f[i]=1e9; m=read();memset(t,63,sizeof t);int l; for(i=1;i<=m;++i) l=read(),v[l-1].push_back(read()); for(i=0;i<n;++i){ f[i+1]=min(f[i+1],f[i]+a[i+1]); for(j=0;j<v[i].size();++j){ int w=min(f[i]+num[v[i][j]]-num[i],query(i,v[i][j])+num[v[i][j]]); f[v[i][j]]=min(f[v[i][j]],w); rw(v[i][j],w-num[v[i][j]]); } } printf("%d\n",f[n]); }
来自PaperCloud的博客,未经允许,请勿转载,TKS!
致虚极,守静笃,万物并作,吾以观其复