zoukankan      html  css  js  c++  java
  • 2018.8.8模拟赛

    T1
    博弈+dp,设f[i][j]表示第f个人报j是否有必胜策略。
    分i+1是不是同类讨论即可。

    #include <iostream>
    #include <queue>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    const int N=5005;
    int n,m,k;
    bool f[N<<1][N];
    int sum[N][N<<1];
    int a[N<<1];
    int rd() {int x;__builtin_scanf("%d",&x);return x;}
    int main() {
    	freopen("vode.in","r",stdin);
    	freopen("vode.out","w",stdout);
    	scanf("%d%d%d",&n,&m,&k);
    	for(int i=1;i<=n;i++)f[i][m-1]=0,a[i]=rd();
    	for(int j=m-2;j>=0;j--) {
    		for(int i=1;i<=n;i++) {
    			int l=i+1;
    			if(l>n) l=1;
    			if(a[l]==a[i]){
    				if(sum[l][j+1]-sum[l][min(j+k,m-1)+1]>0) {
    					f[i][j]=1;
    				}
    			}
    			else {
    				if(sum[l][j+1]-sum[l][min(j+k,m-1)+1]<min(j+k,m-1)-(j+1)+1) f[i][j]=1;
    			}
    			sum[i][j]=sum[i][j+1]+f[i][j];
    		}
    	}
    	for(int i=1;i<=n;i++) {
    		if(f[i][0]==1) printf("%d ",a[i]);
    		else printf("%d ",a[i]^1);
    	}
    }
    

    T2
    给每个点和其上下左右各连一条边,再给其上下左右的各第一堵墙连一条长度为到最近墙的距离的边,跑dij

    #include <iostream>
    #include <queue>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    const int N=505,M=505*505*10;
    struct Edge{int to,nxt,val;}e[M];
    int head[N*N],ecnt,n,m,dis[N*N],leaf,ans[N*N],t[N*N<<2];
    int id(int x,int y) {return (x-1)*m+y;}
    void add(int bg,int ed,int val) {e[++ecnt].nxt=head[bg];e[ecnt].to=ed;e[ecnt].val=val;head[bg]=ecnt;}
    bool g[N][N];
    struct Node{int x,y;}S,T,dir;
    int ck(int x,int y) {
    	return dis[x]<dis[y]?x:y;
    }
    void build(){memset(dis,0x3f,sizeof dis);for(leaf=1;leaf<=n*m;leaf<<=1);leaf--;for(int i=1;i<=n*m;i++) t[leaf+i]=i;}
    void modify(int x,int y){dis[x]=y;x+=leaf;x>>=1;while(x)t[x]=ck(t[x<<1],t[x<<1|1]),x>>=1;} 
    void dij() {
    	build();
    	dis[id(S.x,S.y)]=0;
    	int u=id(S.x,S.y);
    	for(int i=1;i<=n;i++) {
    		for(int j=1;j<=m;j++) {
    		ans[u]=dis[u];
    		int disu=dis[u];
    		modify(u,0x7fffffff);
    		for(int k=head[u];k;k=e[k].nxt) {
    			int v=e[k].to;
    			if(dis[v]<0x7fffffff&&dis[v]>disu+e[k].val) {
    				modify(v,disu+e[k].val);
    				}
    			}
    			u=t[1];
    		}
    		
    	}
    }
    int main() {
    	freopen("portal.in","r",stdin);
    	freopen("portal.out","w",stdout);
    	scanf("%d%d",&n,&m);
    	static char s[605];
    	for(int i=1;i<=n;i++) {
    		scanf("%s",s);
    		for(int j=1;j<=m;j++) {
    			if(s[j-1]=='#') g[i][j]=1;
    			else if(s[j-1]=='C') S.x=i,S.y=j;
    			else if(s[j-1]=='F') T.x=i,T.y=j;
    		}
    	}
    	for(int i=2;i<n;i++) {
    		for(int j=2;j<m;j++) {
    			if(g[i][j]) continue;
    			if(!g[i+1][j]) add(id(i,j),id(i+1,j),1);
    			if(!g[i][j+1]) add(id(i,j),id(i,j+1),1);
    			if(!g[i-1][j]) add(id(i,j),id(i-1,j),1);
    			if(!g[i][j-1]) add(id(i,j),id(i,j-1),1);
    			int tp1=i+1,tp2=i-1,tp3=j+1,tp4=j-1,minn=0x7fffffff;
    			while(!g[tp1][j]) tp1++;if(tp1-i<minn) minn=tp1-i,dir={tp1-1,j};
    			while(!g[tp2][j]) tp2--;if(i-tp2<minn) minn=i-tp2,dir={tp2+1,j};
    			while(!g[i][tp3]) tp3++;if(tp3-j<minn) minn=tp3-j,dir={i,tp3-1};
    			while(!g[i][tp4]) tp4--;if(j-tp4<minn) minn=j-tp4,dir={i,tp4+1};
    			add(id(i,j),id(tp1-1,j),minn);
    			add(id(i,j),id(tp2+1,j),minn);
    			add(id(i,j),id(i,tp3-1),minn);
    			add(id(i,j),id(i,tp4+1),minn);
    		}
    	}
    	dij();
    	if(dis[id(T.x,T.y)]!=0x3f3f3f3f)
    	cout<<ans[id(T.x,T.y)];
    	else puts("nemoguce");
    }
    

    T3
    按秩合并并查集,维护一个时间即可。比可持久化并查集少log^2 n。。。

    #include <bits/stdc++.h>
    using namespace std;
    int n,m,q;
    const int N=100005;
    set<int>s;
    int fa[N],dep[N],t[N];
    int find(int x) {return x==fa[x]?x:find(fa[x]);}
    void merge(int tim,int x,int y) {
    	int fx=find(x),fy=find(y);x=fx,y=fy;
    	if(fx!=fy) {
    		if(dep[fx]<dep[fy]) 
    			fa[x]=y,dep[y]=max(dep[y],dep[x]+1),t[x]=tim;
    		else fa[y]=x,dep[x]=max(dep[x],dep[y]+1),t[y]=tim;
    	}
    }
    bool vis[N];
    int main() {
    	for(int i=0;i<N;i++) fa[i]=i,dep[i]=0,t[i]=0x3f3f3f3f;
    	scanf("%d%d%d",&n,&m,&q);
    	for(int i=1;i<=m;i++) {
    		for(int j=(m-i+1)<<1;j<=n;j+=(m-i+1))
    			merge(i,j,j-(m-i+1));
    	}
    	int x,y;
    	while(q--) {
    		scanf("%d%d",&x,&y);
    		s.clear();
    		int tx=x,ans=0,res,flag=1;
    		while(x!=fa[x]) s.insert(x),x=fa[x];
    		while(y!=fa[y]&& s.count(y)==0){ans=max(ans,t[y]);y=fa[y];}
    		while(tx!=y){ans=max(ans,t[tx]),tx=fa[tx];}
    		
    		printf("%d
    ",ans);
    	}
    }
    
    我是咸鱼。转载博客请征得博主同意Orz
  • 相关阅读:
    Python(2.7.6) 特殊方法
    Python(2.7.6) 列表推导式
    代码神注释鉴赏,喜欢拿去用
    为什么说重启能解决90%的问题
    为什么说重启能解决90%的问题
    编程语言简史
    编程语言简史
    Shell脚本中循环select命令用法笔记
    程序员职业规划
    程序员职业规划
  • 原文地址:https://www.cnblogs.com/sdfzhsz/p/9445633.html
Copyright © 2011-2022 走看看