• 题解-ABC218


    回归了原本的 ABC 难度,可惜我很久没打没有手速被打爆了。

    https://atcoder.jp/contests/abc218/tasks

    A

    直接模拟

    #include<bits/stdc++.h>
    using namespace std;
    int n;
    char s[10]; 
    int main(){
    	scanf("%d%s",&n,s+1);
    	if(s[n]=='o')puts("Yes");
    	else puts("No");
    	return 0;
    }
    

    B

    直接模拟

    #include<bits/stdc++.h>
    using namespace std;
    int main(){
    	for(int i=1;i<=26;i++){
    		int x;
    		scanf("%d",&x);
    		printf("%c",x+'a'-1);
    	}
    	return 0;
    }
    

    C

    考虑将第二图的第一个位置放到第一个第一个位置上,然后比较,较小的模拟

    #include<bits/stdc++.h>
    #define pb push_back
    #define mp make_pair
    using namespace std;
    struct node{
    	char mp[1005][1005];
    }s,t,tmp;
    int n;
    void print(node a){
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=n;j++)printf("%c",a.mp[i][j]);
    		puts("");
    	}puts("");
    }
    bool check(node a,node b){
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=n;j++){
    			if(a.mp[i][j]!=b.mp[i][j]){
    				return 0;
    			}
    		}
    	}
    	return 1;
    }
    void work(node &a,int x0,int y0){
    	node b;
    	for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)b.mp[i][j]='.';
    	int x=0,y=0;
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=n;j++){
    			if(a.mp[i][j]=='#'){
    				x=i,y=j;
    				break;
    			}
    		}
    		if(x||y)break;
    	}
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=n;j++){
    			if(a.mp[i][j]=='#'){
    				b.mp[x0+i-x][y0+j-y]='#';
    			}
    		}
    	}
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=n;j++){
    			a.mp[i][j]=b.mp[i][j];
    		}
    	}
    }
    void rotate(node &a){
    	node b;
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=n;j++){
    			b.mp[n-j+1][i]=a.mp[i][j];	
    		} 
    	}
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=n;j++){
    			a.mp[i][j]=b.mp[i][j];
    		}
    	}
    }
    
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)scanf("%s",s.mp[i]+1);
    	for(int i=1;i<=n;i++)scanf("%s",t.mp[i]+1);
    	int cnts=0,cntt=0;
    	for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)cnts+=s.mp[i][j]=='#';
    	for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)cntt+=t.mp[i][j]=='#';
    	if(cnts!=cntt){
    		puts("No");
    		return 0;
    	}
    	int x=0,y=0;
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=n;j++){
    			if(s.mp[i][j]=='#'){
    				x=i,y=j;
    				break;
    			}
    		}
    		if(x||y)break;
    	}
    	for(int T=1;T<=4;T++){
    		rotate(t);
    		for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)tmp.mp[i][j]=t.mp[i][j];
    		work(tmp,x,y);
    		if(check(s,tmp)){
    			puts("Yes");
    			return 0;
    		}
    	}
    	puts("No");
    	return 0;
    }
    
    

    D

    枚举两个点作为左下角,右上角,然后用map判断即可。

    #include<bits/stdc++.h>
    #define pb push_back
    #define mp make_pair
    using namespace std;
    struct node{
    	int x,y;
    }p[2005];
    int n;
    map<pair<int,int>,int>m;
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)scanf("%d%d",&p[i].x,&p[i].y),m[mp(p[i].x,p[i].y)]++;
    	int ans=0;
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=n;j++){
    			if(i==j)continue;
    			if(p[i].x<p[j].x&&p[i].y<p[j].y){
    				if(m.find(mp(p[i].x,p[j].y))!=m.end()&&m.find(mp(p[j].x,p[i].y))!=m.end()){
    					ans++;
    				}
    			}
    		}
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    
    

    E

    求出最小生成树,其中正权边不能选,取剩下所有正确边。

    #include<bits/stdc++.h>
    #define pb push_back
    #define mp make_pair
    using namespace std;
    typedef long long ll;
    const int maxn=200005;
    struct edge{
    	int u,v,w;
    	friend bool operator<(edge a,edge b){return a.w<b.w;}
    }e[maxn];
    int n,m,fa[maxn];
    int Find(int x){return fa[x]==x?x:fa[x]=Find(fa[x]);}
    inline void Merge(int x,int y){fa[Find(x)]=Find(y);}
    ll ans;
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++)fa[i]=i;
    	for(int i=1;i<=m;i++)scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w),ans+=e[i].w>0?e[i].w:0;
    	sort(e+1,e+1+m);
    	for(int i=1;i<=m;i++){
    		if(Find(e[i].u)!=Find(e[i].v)){
    			if(e[i].w>0)ans-=e[i].w;
    			Merge(e[i].u,e[i].v);
    		}
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    

    F

    求出最短路径树,只有在最短路径树上的路径上的边才有可能改变最短路,去掉暴力bfs即可,复杂度 (O(nm))

    #include<bits/stdc++.h>
    #define pb push_back
    #define mp make_pair
    using namespace std;
    typedef long long ll;
    const int maxn=405;
    int n,m,g[maxn][maxn],s[maxn*maxn],t[maxn*maxn],dis[maxn],pre[maxn],d[maxn];
    queue<int> q;
    bool vis[maxn],mark[maxn];
    int bfs(int x,int y){
    	for(int i=1;i<=n;i++)vis[i]=0,dis[i]=-1;
    	q.push(1);
    	vis[1]=1;
    	dis[1]=0;
    	while(!q.empty()){
    		int u=q.front();q.pop();
    		for(int v=1;v<=n;v++){
    			if(u==x&&v==y)continue;
    			if(g[u][v]&&!vis[v]){
    				dis[v]=dis[u]+1;
    				vis[v]=1;
    				q.push(v);
    			}
    		}
    	}
    	return dis[n];
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;i++)scanf("%d%d",s+i,t+i),g[s[i]][t[i]]=1;
    	for(int i=1;i<=n;i++)vis[i]=0,d[i]=-1;
    	q.push(1);
    	vis[1]=1;d[1]=0;
    	while(!q.empty()){
    		int u=q.front();q.pop();
    		for(int v=1;v<=n;v++){
    			if(g[u][v]&&!vis[v]){
    				d[v]=d[u]+1;
    				pre[v]=u;
    				vis[v]=1;
    				q.push(v);
    			}
    		}
    	}
    	if(d[n]==-1){
    		for(int i=1;i<=m;i++)puts("-1");
    		return 0;
    	}
    	int x=n;
    	while(x!=1){
    		mark[x]=1;
    		x=pre[x];
    	}
    	for(int i=1;i<=m;i++){
    		if(!mark[t[i]])printf("%d
    ",d[n]);
    		else{
    			if(s[i]!=pre[t[i]])printf("%d
    ",d[n]);
    			else{
    				printf("%d
    ",bfs(s[i],t[i]));
    			}
    		}
    	}
    	return 0;
    }
    

    G

    博弈,然后瞎转移,用数据结构维护中位数即可。

    #include<bits/stdc++.h>
    #define pb push_back
    #define mp make_pair
    using namespace std;
    typedef long long ll;
    const int maxn=100005;
    struct node{
    	int val,key,son[2],sz;
    }tr[maxn*40];
    int tot,rt,dep[maxn];
    int new_node(int v){
    	tr[++tot]=node{v,rand(),0,0,1};
    	return tot;
    }
    void pushup(int p){
    	tr[p].sz=tr[tr[p].son[0]].sz+tr[tr[p].son[1]].sz+1;
    }
    int merge(int u,int v){
    	if(!u||!v)return u|v;
    	if(tr[u].key<tr[v].key){
    		tr[u].son[1]=merge(tr[u].son[1],v);
    		pushup(u);
    		return u;
    	}else{
    		tr[v].son[0]=merge(u,tr[v].son[0]);
    		pushup(v);
    		return v;
    	}
    }
    void split(int p,int &x,int &y,int k){
    	if(!p)x=y=0;
    	else{
    		if(tr[p].val<=k){
    			x=p;
    			split(tr[p].son[1],tr[x].son[1],y,k); 
    		}else{
    			y=p;
    			split(tr[p].son[0],x,tr[y].son[0],k);
    		}
    		pushup(p);
    	}
    }
    void ins(int &p,int v){
    	int x,y;
    	split(p,x,y,v);
    	p=merge(merge(x,new_node(v)),y);
    }
    void del(int &p,int v){
    	int x,y,z;
    	split(p,x,z,v);
    	split(x,x,y,v-1);
    	y=merge(tr[y].son[0],tr[y].son[1]);
    	p=merge(merge(x,y),z);
    }
    int ath(int p,int a){
    	if(tr[tr[p].son[0]].sz>=a)return ath(tr[p].son[0],a);
    	else{
    		a-=tr[tr[p].son[0]].sz;
    		if(a==1)return tr[p].val;
    		return ath(tr[p].son[1],a-1);
    	}
    }
    int n,a[maxn],f[maxn];
    vector<int> vec[maxn];
    void dfs(int u,int fa){
    	int cnt=0;
    	ins(rt,a[u]);
    	if(dep[u]&1)f[u]=0;
    	else f[u]=1e9+1; 
    	for(auto v:vec[u]){
    		if(v==fa)continue;
    		dep[v]=dep[u]+1;
    		dfs(v,u);
    		if(dep[u]&1)f[u]=max(f[u],f[v]);
    		else f[u]=min(f[u],f[v]);
    		cnt++;
    	}
    	if(cnt==0){
    		if(dep[u]&1)f[u]=ath(rt,(dep[u]+1)/2);
    		else f[u]=(ath(rt,dep[u]/2)+ath(rt,dep[u]/2+1))/2;
    		del(rt,a[u]);
    		return;
    	}
    	del(rt,a[u]);
    }
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)scanf("%d",a+i);
    	for(int i=1,u,v;i<n;i++){
    		scanf("%d%d",&u,&v);
    		vec[u].pb(v);vec[v].pb(u);
    	}
    	dep[1]=1;dfs(1,0);
    	printf("%d
    ",f[1]);
    	return 0;
    }
    

    H

    显然这东西有凸性,于是 wqs 二分+普及组dp即可。

    /*
      Author : Flying_Bird (ZCR)
      url : https://nmsl.com
      Time : 2021/09/01
    */
    #include<bits/stdc++.h>
    #define pb push_back
    #define mp make_pair
    using namespace std;
    typedef long long ll;
    const ll maxn=200005;
    ll n,R,a[maxn];
    ll dp[maxn][2],cnt[maxn][2];
    bool check(ll m){
    	dp[1][1]=m;cnt[1][1]=1;
    	for(ll i=2;i<=n;i++){
    		if(dp[i-1][0]<dp[i-1][1]+a[i-1]){
    			dp[i][0]=dp[i-1][1]+a[i-1];
    			cnt[i][0]=cnt[i-1][1];
    		}else{
    			dp[i][0]=dp[i-1][0];
    			cnt[i][0]=cnt[i-1][0];
    		}
    		if(dp[i-1][1]>dp[i-1][0]+a[i-1]){
    			dp[i][1]=dp[i-1][1]+m;
    			cnt[i][1]=cnt[i-1][1]+1;
    		}else{
    			dp[i][1]=dp[i-1][0]+a[i-1]+m;
    			cnt[i][1]=cnt[i-1][0]+1;
    		}
    	}
    	if(dp[n][0]>dp[n][1]){
    		return cnt[n][0]>R;
    	}else{
    		return cnt[n][1]>R;
    	}
    }
    int main(){
    	scanf("%lld%lld",&n,&R);
    	for(ll i=1;i<n;i++)scanf("%lld",a+i);
    	ll l=-4e9,r=4e9,ans=-4e9;
    	while(l<=r){
    		ll mid=(l+r)>>1;
    		check(mid);
    		if(check(mid)){
    			r=mid-1;
    		}else{
    			ans=mid;
    			l=mid+1;
    		}
    	}
    	check(ans);
    	if(dp[n][0]>dp[n][1]){
    		printf("%lld
    ",dp[n][0]-ans*R);
    	}else{
    		printf("%lld
    ",dp[n][1]-ans*R);
    	}
    	return 0;
    }
    
  • 相关阅读:
    奥一新源科技 面试总结
    腾讯实习 面试总结
    图片预加载 解决图片加载闪动问题
    “-webkit-font-smoothing”
    onselectstart
    jquery 高级 学习笔记
    css 样式重置
    《响应式Web设计—HTML5和CSS3实战》 学习记录
    shift、unshift、 push、pop用法--JavaScript参考手册
    《JavaScript DOM 编程艺术 》 笔记
  • 原文地址:https://www.cnblogs.com/zcr-blog/p/15256962.html
Copyright © 2020-2023  润新知