A组
T1.vode 没有硝烟的战争
#include<iostream> #include<cstdio> #include<set> using namespace std; inline int rd(){ int ret=0,f=1;char c; while(c=getchar(),!isdigit(c))f=c=='-'?-1:1; while(isdigit(c))ret=ret*10+c-'0',c=getchar(); return ret*f; } const int MAXN=5005; int n,m,num; int a[MAXN],tot; bool f[MAXN<<1][MAXN]; int main(){ freopen("vode.in","r",stdin); freopen("vode.out","w",stdout); n=rd();m=rd();num=rd(); for(int i=1;i<=n;i++){ a[i]=rd(); } for(int i=n+m-1;i>=1;i--){ int sum=0; for(int j=m-1;j>=1;j--){ int k=i%n?i%n:n; int nxt=k==n?1:k+1; if(a[k]==a[nxt]) f[i][j]=sum>0; else f[i][j]=sum==0; sum+=f[i+1][j]; if(j+num<=m) sum-=f[i+1][j+num]; } } for(int i=1;i<=n;i++){ for(int j=1;j<=num;j++){ f[i][0]|=f[i][j]; } } for(int i=1;i<=n;i++) printf("%d ",f[i][0]?a[i]:a[i]^1); return 0; }
T2.portal 秘密通道
写了BFS,挂了四个点,有三个完全不知道为什么
正解是暴力连边跑最短路。
UPD:存在这样一种情况,先向一个方向射击,再移动到墙边传送,搜索没有考虑这种情况
9 6 ###### #.F..# ###..# #....# #.C..# #....# #.#.## #...## ######
#include<iostream> #include<cstring> #include<cstdio> #include<queue> using namespace std; const int MAXN=1005; inline int rd() { int ret=0,f=1; char c; while(c=getchar(),!isdigit(c))f=c=='-'?-1:1; while(isdigit(c))ret=ret*10+c-'0',c=getchar(); return ret*f; } struct Edge { int next,to,w; } e[MAXN*MAXN*2]; int ecnt,head[MAXN*MAXN]; int sx,sy,fx,fy; inline void add(int x,int y,int w) { e[++ecnt].next = head[x]; e[ecnt].to = y; e[ecnt].w = w; head[x] = ecnt; } #define id(x,y) ((x-1)*(m)+(y)) int n,m; char a[MAXN][MAXN],s[MAXN]; int dx[5]= {0,0,-1,0,1}; int dy[5]= {0,1,0,-1,0}; struct Node { int id,w; Node(int x=0,int y=0) { id=x; w=y; } bool operator<(const Node &rhs)const { return w>rhs.w; } } top; bool vis[MAXN*MAXN]; int dis[MAXN*MAXN]; priority_queue<Node> Q; void dij(int st) { memset(dis,0x3f,sizeof(dis)); memset(vis,0,sizeof(vis)); dis[st]=0; Q.push(Node(st,0)); while(!Q.empty()) { top=Q.top(); Q.pop(); int mn=top.w,mnid=top.id; if(dis[mnid]!=mn) continue; vis[mnid]=1; for(int j=head[mnid]; j; j=e[j].next) { int v=e[j].to; if(dis[v]>mn+e[j].w) { dis[v]=mn+e[j].w; Q.push(Node(v,dis[v])); } } } } int d1[MAXN*MAXN],d2[MAXN*MAXN],d3[MAXN*MAXN],d4[MAXN*MAXN],d[MAXN*MAXN]; int main() { n=rd(); m=rd(); memset(d,0x3f,sizeof(d)); for(register int i=1; i<=n; i++) { scanf("%s",s+1); for(register int j=1; j<=m; j++) { a[i][j]=s[j]; if(s[j]=='C') sx=i,sy=j; if(s[j]=='F') fx=i,fy=j; } } int x,y; for(int i=2; i<=n-1; i++) { for(int j=2; j<=m-1; j++) { if(a[i][j]=='#') continue; for(int k=1; k<=4; k++) { x=i+dx[k]; y=j+dy[k]; if(a[x][y]=='#') continue; // if(i==sx&&j==sy) cout<<x<<" "<<y<<" ! "; add(id(i,j),id(x,y),1); } } } for(x=2; x<=n-1; x++) { for(y=2; y<=m-1; y++) { if(a[x][y]=='#') continue; register int j; for(j=x; a[j+1][y]!='#'; j++); d1[id(x,y)]=id(j,y); d[id(x,y)]=min(d[id(x,y)],j-x+1); for(j=x; a[j-1][y]!='#'; j--); d2[id(x,y)]=id(j,y); d[id(x,y)]=min(d[id(x,y)],x-j+1); for(j=y; a[x][j+1]!='#'; j++); d3[id(x,y)]=id(x,j); d[id(x,y)]=min(d[id(x,y)],j-y+1); for(j=y; a[x][j-1]!='#'; j--); d4[id(x,y)]=id(x,j); d[id(x,y)]=min(d[id(x,y)],y-j+1); } } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(a[i][j]=='#') continue; add(id(i,j),d1[id(i,j)],d[id(i,j)]); add(id(i,j),d2[id(i,j)],d[id(i,j)]); add(id(i,j),d3[id(i,j)],d[id(i,j)]); add(id(i,j),d4[id(i,j)],d[id(i,j)]); } } dij(id(sx,sy)); if(dis[id(fx,fy)]==0x3f3f3f3f) puts("nemoguce"); else cout<<dis[id(fx,fy)]; }
#include<iostream> #include<cstring> #include<cstdio> #include<vector> #include<queue> using namespace std; inline int rd(){ int ret=0,f=1;char c; while(c=getchar(),!isdigit(c))f=c=='-'?-1:1; while(isdigit(c))ret=ret*10+c-'0',c=getchar(); return ret*f; } const int MAXN=512; struct Node{ int x,y,cost; }node,top; queue<Node> Q; int n,m; char a[MAXN][MAXN],s[MAXN]; int sx,sy; int vis[MAXN][MAXN]; int dx[5]={0,0,-1,0,1}; int dy[5]={0,1,0,-1,0}; int main(){ // freopen("portal.in","r",stdin); // freopen("portal.out","w",stdout); n=rd();m=rd(); for(register int i=1;i<=n;i++){ scanf("%s",s+1); for(register int j=1;j<=m;j++){ a[i][j]=s[j]; if(s[j]=='C') sx=i,sy=j; } } for(register int i=0;i<=n+1;i++) a[i][0]=a[i][m+1]='#'; for(register int i=0;i<=m+1;i++) a[0][i]=a[n+1][i]='#'; node.cost=0;node.x=sx;node.y=sy; Q.push(node);vis[sx][sy]=1; while(!Q.empty()){ top=Q.front();Q.pop(); int x=top.x,y=top.y,nx,ny,cost=top.cost; // cout<<x<<" "<<y<<" "<<cost<<endl; if(a[x][y]=='F') return printf("%d",cost),0; bool succ=0; for(register int i=1;i<=4;i++){ if(a[x+dx[i]][y+dy[i]]!='#') continue; succ=1;break; } if(!succ) goto lab; register int j; for(j=x;a[j+1][y]!='#';j++); if(!vis[j][y]) { vis[j][y]=node.cost=cost+1; node.x=j;node.y=y; Q.push(node); } for(j=x;a[j-1][y]!='#';j--); if(!vis[j][y]) { vis[j][y]=node.cost=cost+1; node.x=j;node.y=y; Q.push(node); } for(j=y;a[x][j+1]!='#';j++); if(!vis[x][j]) { vis[x][j]=node.cost=cost+1; node.x=x;node.y=j; Q.push(node); } for(j=y;a[x][j-1]!='#';j--); if(!vis[x][j]) { vis[x][j]=node.cost=cost+1; node.x=x;node.y=j; Q.push(node); } lab: for(register int i=1;i<=4;i++){ nx=x+dx[i];ny=y+dy[i]; if(a[nx][ny]=='#') continue; if(vis[nx][ny]) continue; vis[nx][ny]=node.cost=cost+1; node.x=nx;node.y=ny; Q.push(node); } } puts("nemoguce"); return 0; }
T3.pictionary 城市猎人
考场枚举了每个点对的连接时间,然后跑最短路..
连边确实具有连通块的性质,所以可以用并查集维护,但是并不需要可持久化,有个优秀的做法。
考虑使用按秩合并的并查集,构造出一个并查集树,边权为这两个集合连接的时间,边数是一个调和级数,大概在NlnN的级别,可以暴力建图,而按秩合并的并查集树高稳定在logn级别(树高一层,节点数至少乘以2)
这样就可以暴力求树上两点的路径上的最大值了。
#include<iostream> #include<cstdio> #include<set> using namespace std; inline int rd(){ int ret=0,f=1;char c; while(c=getchar(),!isdigit(c))f=c=='-'?-1:1; while(isdigit(c))ret=ret*10+c-'0',c=getchar(); return ret*f; } const int MAXN=100005; int n,m,q; int val[MAXN],fa[MAXN],siz[MAXN]; int fnd(int x){return x==fa[x]?x:fnd(fa[x]);} void cat(int x,int y,int t){ x=fnd(x);y=fnd(y); if(x==y) return; if(siz[x]<siz[y]) { fa[x]=y;val[x]=t; siz[y]+=siz[x]; }else{ fa[y]=x;val[y]=t; siz[x]+=siz[y]; } } set<int> S; int main(){ // freopen("pictionary.in","r",stdin); // freopen("pictionary.out","w",stdout); n=rd();m=rd();q=rd(); for(int i=1;i<=n;i++) fa[i]=i,siz[i]=1; for(int i=1;i<=m;i++){ int tmp=m-i+1; for(int j=tmp*2;j<=n;j+=tmp){ cat(j,j-tmp,i); } } int x,y,sav,ans; for(int i=1;i<=q;i++){ S.clear();ans=0; sav=x=rd();y=rd(); while(x!=fa[x]) S.insert(x),x=fa[x]; while(!S.count(y)&&y!=fa[y]) ans=max(ans,val[y]),y=fa[y]; while(sav!=y) ans=max(ans,val[sav]),sav=fa[sav]; printf("%d ",ans); } return 0; }