A思路:排个序建立最短路树即可,可以双指针实现。
考察:贪心,构造。
#include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=2000010; struct in{ int x,id; bool friend operator <(in w,in v){ if(w.x==v.x) return w.id<v.id; return w.x<v.x; } }s[maxn]; int a[maxn],b[maxn],c[maxn],tot; int q[maxn],head,tail; int main() { int N,M; scanf("%d%d",&N,&M); rep(i,1,N) scanf("%d",&s[i].x),s[i].id=i; sort(s+1,s+N+1); q[++head]=1; rep(i,2,N) { while(head>tail&&s[i].x-s[q[tail+1]].x>M) tail++; if(head>tail){ a[i]=s[q[tail+1]].id; b[i]=s[i].id; c[i]=s[i].x-s[q[tail+1]].x; } q[++head]=i; if(c[i]==0) { puts("-1"); return 0; } } printf("%d ",N-1); rep(i,2,N) printf("%d %d %d ",a[i],b[i],c[i]); return 0; }
B:显然最大值取决于a[],出现的最高位不同的那一位,假设有最高位的分到A组,不然分到B组,分组后,各取一个x,y,那么ans=min(x^y),这个可以字典树实现。
比较常规。 但是比赛的时候我以为字典树空间不够只能得80分。所以写了分治, 分治复杂度也是O(60*N)的,而且感觉比字典树保险,实现就是每一层,继续分组。
考察:贪心,字典树求最小异或。
#include<bits/stdc++.h> #define ll long long #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=2000010; ll a[maxn],b[maxn],c[maxn],ans=0; void solve(int p,int L1,int R1,int L2,int R2,ll sum) {if(p==-1){ ans=min(ans,sum); return ; } int t1=0,t2=0; for(int i=L1;i<=R1;i++){ if(a[i]&(1LL<<p)) b[++t1]=a[i]; else c[++t2]=a[i]; } rep(i,1,t1) a[L1+i-1]=b[i]; rep(i,1,t2) a[L1+t1+i-1]=c[i]; int t3=0,t4=0; for(int i=L2;i<=R2;i++){ if(a[i]&(1LL<<p)) b[++t3]=a[i]; else c[++t4]=a[i]; } rep(i,1,t3) a[L2+i-1]=b[i]; rep(i,1,t4) a[L2+t3+i-1]=c[i]; int F=0; if(t1&&t3) F=1,solve(p-1,L1,L1+t1-1,L2,L2+t3-1,sum); if(t2&&t4) F=1,solve(p-1,L1+t1,R1,L2+t3,R2,sum); if(F) return ; solve(p-1,L1,R1,L2,R2,sum+(1LL<<p)); } int main() { int N; scanf("%d",&N); rep(i,1,N) scanf("%lld",&a[i]); int p=-1; for(int i=60;i>=0;i--){ int tot=0; rep(j,1,N) if(a[j]&(1LL<<i)) tot++; if(tot!=0&&tot!=N) { p=i; break; } } if(p!=-1){ int t1=0,t2=0; ans=1LL<<61; rep(i,1,N) { if(a[i]&(1LL<<p)) b[++t1]=a[i]; else c[++t2]=a[i]; } rep(i,1,t1) a[i]=b[i]; rep(i,1,t2) a[t1+i]=c[i]; solve(p-1,1,t1,t1+1,N,1LL<<p); } printf("%lld ",ans); return 0; }
C:求最小字典序下的公共路径长度,由于N比较小,显然就是枚举每个点为根,然后最小字典序的 Σ最短路树LCA到根的距离,预料到码量比较长,就写了个floyd骗分,LCA也直接写的倍增(估计写tarjan会快个10倍),70分水过。 字典序那里先排个序,然后记忆化搜索实线。
考察:最短路,LCA,保证字典序。
#include<bits/stdc++.h> #define pii pair<int,int> #define mp make_pair #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int inf=1e9; const int maxn=2001; int dis[maxn][maxn]; int Laxt[maxn],Next[6001],To[6001],len[6001],cnt; int a[6001],b[6001],fa[maxn][12],ans[6001],dep[maxn],N,Q; bool vis[maxn]; int ind[maxn]; vector<int>G[maxn]; void add(int u,int v,int w) { Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v; len[cnt]=w; } int LCA(int u,int v) { if(dep[u]<dep[v]) swap(u,v); for(int i=11;i>=0;i--) { if(dep[fa[u][i]]>=dep[v]) u=fa[u][i]; } if(u==v) return u; for(int i=11;i>=0;i--) if(fa[u][i]!=fa[v][i]) u=fa[u][i],v=fa[v][i]; return fa[u][0]; } set<pii>s; void dfs(int u,int f) { if(vis[u]) return ; vis[u]=1; fa[u][0]=f; dep[u]=dep[f]+1; for(int i=0;i<G[u].size();i++) dfs(G[u][i],u); } void solve(int p) { rep(i,1,N) vis[i]=0; rep(i,1,N) G[i].clear(); rep(i,1,N) for(int j=Laxt[i];j;j=Next[j]){ if(dis[p][i]+len[j]==dis[p][To[j]]) G[i].push_back(To[j]); } rep(i,1,N) sort(G[i].begin(),G[i].end()); dfs(p,0); rep(i,1,11) rep(j,1,N) fa[j][i]=fa[fa[j][i-1]][i-1]; rep(i,1,Q){ if(!vis[a[i]]||!vis[b[i]]) continue; ans[i]=max(ans[i],dis[p][LCA(a[i],b[i])]); } } int main() { int M,u,v,w; scanf("%d%d%d",&N,&M,&Q); rep(i,1,Q) ans[i]=-1; rep(i,1,N) rep(j,1,N) dis[i][j]=inf; rep(i,1,N) dis[i][i]=0; rep(i,1,M) { scanf("%d%d%d",&u,&v,&w); add(u,v,w); dis[u][v]=min(dis[u][v],w); } rep(i,1,Q) scanf("%d%d",&a[i],&b[i]); rep(k,1,N) rep(i,1,N) if(dis[i][k]!=inf) rep(j,1,N) dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]); rep(i,1,N) solve(i); rep(i,1,Q) printf("%d ",ans[i]); return 0; }
改为dijstra变为90分了:
#include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int inf=1e9; const int maxn=2001; int dis[maxn][maxn]; bool vis[maxn]; int Laxt[maxn],Next[6001],To[6001],len[6001],cnt; int a[6001],b[6001],ans[6001],dep[maxn],N,Q; vector<int>G[maxn],P[maxn]; int son[maxn],sz[maxn],Tp[maxn],fa[maxn]; void add(int u,int v,int w) { Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v; len[cnt]=w; } void dfs1(int u,int f) { sz[u]=1; son[u]=0; dep[u]=dep[f]+1; fa[u]=f; for(int i=0;i<P[u].size();i++){ if(!son[P[u][i]]) { int v=P[u][i]; dfs1(v,u); sz[u]+=sz[v]; if(sz[v]>sz[son[u]]) son[u]=v; } } } void dfs2(int u,int tp) { Tp[u]=tp; if(son[u]) dfs2(son[u],tp); for(int i=0;i<P[u].size();i++){ if(P[u][i]!=son[u]) dfs2(P[u][i],P[u][i]); } } int LCA(int u,int v) { while(Tp[u]^Tp[v]) dep[Tp[u]]<dep[Tp[v]]?v=fa[Tp[v]]:u=fa[Tp[u]]; return dep[u]<dep[v]?u:v; } void dfs(int u,int f) { if(vis[u]) return ; vis[u]=1; P[f].push_back(u); for(int i=0;i<G[u].size();i++) dfs(G[u][i],u); } struct ww{ int dis,u; bool friend operator <(ww w,ww v){ return w.dis>v.dis; } }; priority_queue<ww>q; int inq[maxn]; void SPFA(int S) { rep(i,1,N) dis[S][i]=inf; dis[S][S]=0; q.push(ww{0,S}); while(!q.empty()){ int u=q.top().u; q.pop(); inq[u]=0; for(int i=Laxt[u];i;i=Next[i]) { int v=To[i]; if(dis[S][v]>dis[S][u]+len[i]){ dis[S][v]=dis[S][u]+len[i]; if(!inq[v]) inq[v]=1,q.push(ww{dis[S][v],v}); } } } } void solve(int p) { rep(i,1,N) vis[i]=son[i]=0; rep(i,0,N) G[i].clear(),P[i].clear(); rep(i,1,N) for(int j=Laxt[i];j;j=Next[j]){ if(dis[p][i]+len[j]==dis[p][To[j]]) G[i].push_back(To[j]); } rep(i,1,N) sort(G[i].begin(),G[i].end()); dfs(p,0); dfs1(p,0); dfs2(p,p); rep(i,1,Q){ if(!vis[a[i]]||!vis[b[i]]) continue; ans[i]=max(ans[i],dis[p][LCA(a[i],b[i])]); } } int main() { int M,u,v,w; scanf("%d%d%d",&N,&M,&Q); rep(i,1,Q) ans[i]=-1; rep(i,1,N) rep(j,1,N) dis[i][j]=inf; rep(i,1,N) dis[i][i]=0; rep(i,1,M) { scanf("%d%d%d",&u,&v,&w); add(u,v,w); } rep(i,1,Q) scanf("%d%d",&a[i],&b[i]); rep(i,1,N) SPFA(i); rep(i,1,N) solve(i); rep(i,1,Q) printf("%d ",ans[i]); return 0; }
按照题解写的,还是90分:
#include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int inf=1e9; const int maxn=2001; int dis[maxn][maxn]; bool vis[maxn]; int Laxt[maxn],Next[6001+maxn],To[6001+maxn],len[6001+maxn],cnt; int a[6001],b[6001],ans[6001],dep[maxn],N,Q; vector<int>G[maxn],P[maxn]; int son[maxn],sz[maxn],Tp[maxn],fa[maxn]; void add(int u,int v,int w) { Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v; len[cnt]=w; } void dfs1(int u,int f) { sz[u]=1; son[u]=0; dep[u]=dep[f]+1; fa[u]=f; for(int i=0;i<P[u].size();i++){ if(!son[P[u][i]]) { int v=P[u][i]; dfs1(v,u); sz[u]+=sz[v]; if(sz[v]>sz[son[u]]) son[u]=v; } } } void dfs2(int u,int tp) { Tp[u]=tp; if(son[u]) dfs2(son[u],tp); for(int i=0;i<P[u].size();i++){ if(P[u][i]!=son[u]) dfs2(P[u][i],P[u][i]); } } int LCA(int u,int v) { while(Tp[u]^Tp[v]) dep[Tp[u]]<dep[Tp[v]]?v=fa[Tp[v]]:u=fa[Tp[u]]; return dep[u]<dep[v]?u:v; } void dfs(int u,int f) { if(vis[u]) return ; vis[u]=1; P[f].push_back(u); for(int i=0;i<G[u].size();i++) dfs(G[u][i],u); } struct ww{ int dis,u; bool friend operator <(ww w,ww v){ return w.dis>v.dis; } }; priority_queue<ww>q; int inq[maxn],h[maxn]; void SPFA(int S) { rep(i,0,N) dis[S][i]=inf; dis[S][S]=0; q.push(ww{0,S}); while(!q.empty()){ int u=q.top().u; q.pop(); inq[u]=0; for(int i=Laxt[u];i;i=Next[i]) { int v=To[i]; if(dis[S][v]>dis[S][u]+len[i]){ dis[S][v]=dis[S][u]+len[i]; if(!inq[v]) inq[v]=1,q.push(ww{dis[S][v],v}); } } } if(S==0) { rep(i,1,N) h[i]=dis[S][i]; rep(i,1,N) for(int j=Laxt[i];j;j=Next[j]) len[j]=len[j]+h[i]-h[To[j]]; } else { rep(i,1,N) if(dis[S][i]!=inf) dis[S][i]=dis[S][i]+h[i]-h[S]; } } void solve(int p) { rep(i,1,N) vis[i]=son[i]=0; rep(i,0,N) G[i].clear(),P[i].clear(); rep(i,1,N) for(int j=Laxt[i];j;j=Next[j]){ if(dis[p][i]+len[j]-h[i]+h[To[j]]==dis[p][To[j]]) G[i].push_back(To[j]); } rep(i,1,N) sort(G[i].begin(),G[i].end()); dfs(p,0); dfs1(p,0); dfs2(p,p); rep(i,1,Q){ if(!vis[a[i]]||!vis[b[i]]) continue; ans[i]=max(ans[i],dis[p][LCA(a[i],b[i])]); } } int main() { int M,u,v,w; scanf("%d%d%d",&N,&M,&Q); rep(i,1,Q) ans[i]=-1; rep(i,1,N) rep(j,1,N) dis[i][j]=inf; rep(i,1,N) dis[i][i]=0; rep(i,1,N) add(0,i,0); rep(i,1,M) { scanf("%d%d%d",&u,&v,&w); add(u,v,w); } rep(i,1,Q) scanf("%d%d",&a[i],&b[i]); rep(i,0,N) SPFA(i); rep(i,1,N) solve(i); rep(i,1,Q) printf("%d ",ans[i]); return 0; }