zoukankan      html  css  js  c++  java
  • Codeforces Round#615 Div.3 解题报告

    前置扯淡

    真是神了,我半个小时切前三题(虽然还是很菜)

    然后就开始看(D),不会;

    接着看(E)(dp)看了半天,交了三次还不行

    然后看(F):一眼(LCA)瞎搞,然后(15min space A)

    幸亏加时了(10min),否则(F)(AC)不掉啥没有了

    送我自闭,如果先全看一遍,发现(D)题和(E)题都不可做,直接刚(F),新年就上蓝了(然而还是菜)

    题目&&解答

    A.Collecting Coins

    link

    思路

    这水题吧,就是需要特判一下是不是有一个人的个数多于平均数了

    CODE:

    #include<bits/stdc++.h> 
    using namespace std;
    inline void work()
    {
    	int a,b,c,n;
    	cin>>a>>b>>c>>n;
    	int sum=a+b+c+n; 
    	if(sum%3!=0) return puts("NO"),void();
    	sum/=3; if(c>sum||a>sum||b>sum) return puts("NO"),void();
    	return puts("YES"),void();
    }
    int main()
    {
    	int T; cin>>T; while(T--) work();	
    	return 0;
    }
    

    B. Collecting Packages

    link

    思路

    一眼贪心,(sort+check)一波

    有一些细节(可能是我代码能力太差)

    CODE:

    (直接放代码了)

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    namespace yspm{
    	inline int read()
    	{
    		int res=0,f=1; char k;
    		while(!isdigit(k=getchar())) if(k=='-') f=-1;
    		while(isdigit(k)) res=res*10+k-'0',k=getchar();
    		return res*f;
    	}
    	const int N=1010;
    	struct node{
    		int x,y;
    	}p[N];
    	int n;
    	inline bool cmp(node a,node b)
    	{
    		if(a.x==b.x) return a.y<b.y;
    		return a.x<b.x;
    	}
    	inline void work()
    	{
    		n=read(); for(int i=1;i<=n;++i) p[i].x=read(),p[i].y=read();
    		sort(p+1,p+n+1,cmp);
    		for(int i=1;i<=n;++i)
    		{
    			for(int j=i+1;j<=n;++j) 
    			{
    				if(p[i].x<p[j].x&&p[i].y>p[j].y) return puts("NO"),void();
    			}
    		}puts("YES");
    		int nx=0,ny=0;
    		for(int i=1;i<=n;++i)
    		{
    			for(int j=1;j<=p[i].x-nx;++j) putchar('R');
    			for(int j=1;j<=p[i].y-ny;++j) putchar('U');
    			nx=p[i].x,ny=p[i].y;
    		}
    		return puts(""),void();
    	}
    	signed main()
    	{
    		int T=read(); while(T--) work();
    		return 0;
    	}
    }
    signed main(){yspm::main(); return 0;}
    

    C. Product of Three Numbers

    link

    思路

    一眼可能会比较复杂,但是当你发现这个题放(O(sqrt n))算法就很可做了吧,

    就是分解一下(n),然后就是合并你分解出来的结果(有些奇怪的情况,代码可懂)

    CODE:

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    namespace yspm{
    	inline int read()
    	{
    		int res=0,f=1; char k;
    		while(!isdigit(k=getchar())) if(k=='-') f=-1;
    		while(isdigit(k)) res=res*10+k-'0',k=getchar();
    		return res*f;
    	}
    	inline void work()
    	{
    		int n=read(),ans[10010],tot=0;
    		for(int i=2;i*i<=n;++i)
    		{
    			if(n%i==0) ans[++tot]=i,n/=i;
    		} 
    		if(n!=1) 
    		{
    			bool flag=0;
    			for(int i=1;i<=tot;++i) if(n==ans[i]){ans[i]*=n; flag=1;} if(!flag) ans[++tot]=n;
    		}
    		if(tot<=2) return puts("NO"),void();
    		if(tot>3) for(int i=4;i<=tot;++i) ans[3]*=ans[i];
    		puts("YES");
    		cout<<ans[1]<<" "<<ans[2]<<" "<<ans[3]<<endl;; 
    		return ;
    	}
    	signed main()
    	{
    		int T=read(); while(T--) work();
    		return 0;
    	}
    }
    signed main(){yspm::main(); return 0;}
    

    D.MEX maximizing

    link

    woc 比赛的时候看错题了!!!没看出来可以操作任意次可还行!!!

    这要是翻译出来正确题意,再想不出来用同余就退赛吧……(反正有qjjh)

    思路

    记录关于(x)同余下各个数字的结果,然后桶一波,还是模拟就可以了……

    外语水平严重不足(其实就是依赖百度翻译),导致这个题只能补了2444

    CODE:

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    namespace yspm{
    	inline int read()
    	{
    		int res=0,f=1; char k;
    		while(!isdigit(k=getchar())) if(k=='-') f=-1;
    		while(isdigit(k)) res=res*10+k-'0',k=getchar(); 
    		return res*f;
    	}
    	const int N=4e5+10;
    	int n,x,y,p,q,cnt[N],app[N];
    	signed main()
    	{
    		n=read(); x=read(); app[0]=x;
    		for(int i=1;i<=n;++i)
    		{
    			y=read()%x;
    			app[cnt[y]]--; cnt[y]++; app[cnt[y]]++; 
    			if(!app[p]) ++p,q=0;
    			while(cnt[q]>p) ++q; 
    			printf("%lld
    ",p*x+q);
    		}
    		return 0;
    	}
    }
    signed main(){return yspm::main();} 
    

    E.Obtain a Permutation

    link

    思路

    首先有每一列都是无关的,单独处理就行(这要是行列相关就很复杂了)

    然后就变成了一个(dp)(m)遍?

    同是(O(n * m))的复杂度,我死活比赛过不去

    (现在知道了,(memset)的复杂度是(O(n))的,循环套(memset)卡到(O(n^2))现场)

    思路其实跟正解一样,但是不知道为啥不行2444

    写法就是我们看每一个列上的数是不是符合“不改”的要求,这个取模就可以办到,如果不行,肯定要修改(无论在什么位置)

    然后看每个数转几次就可以到它应该在的位置(这个求两个位置的移动次数很简单,画下图就可以)

    然后开桶,看哪个最多就选择转哪个,最后统计答案

    CODE:

    #include<bits/stdc++.h>
    #define reg register
    using namespace std;
    namespace yspm{
    	inline int read()
    	{
    		int res=0,f=1; char k;
    		while(!isdigit(k=getchar())) if(k=='-') f=-1;
    		while(isdigit(k)) res=res*10+k-'0',k=getchar();
    		return res*f;
    	}
    	const int N=2e5+10;
    	int n,m,app[N],ans;
    	vector<int> vec[N];
    	signed main()
    	{
    		n=read(); m=read(); 
    		for(reg int i=1;i<=n;++i)
    		{
    			vec[i].push_back(0); 
    			for(reg int j=1;j<=m;++j) vec[i].push_back(read());
    		}
    		for(reg int j=1;j<=m;++j)
    		{
    			int tmp=2e9+10; for(int i=0;i<n;++i) app[i]=0;
    			for(reg int i=1;i<=n;++i)
    			{
    				if(vec[i][j]<j||vec[i][j]>n*m||(vec[i][j]-j)%m!=0) continue;
    				int k=(vec[i][j]-j)/m+1; app[(i-k+n)%n]++;
    			}
    			for(reg int i=0;i<n;++i) tmp=min(tmp,i+n-app[i]); ans+=tmp; 
    		} printf("%d
    ",ans);
    		return 0;
    	}
    }
    signed main(){return yspm::main();}
    

    F.Three Paths on a Tree

    link

    思路

    题意就是树上任意三个点,求三个点的各自路径上的边数总和最大(这里点还是边无所谓,反正(lca)(dis)的时候卡一下就好)

    首先,三个点其中必有两个点是直径

    这个结论显然吧(应该贪心地想一下就完事)

    之后我们发现数据放了(O(nlog space n))

    所以第三个点枚举算就好

    其实这个地方还有一个重要的定理:树的叶节点只有连向其父节点的一条边(显然是废话)

    我们两遍(dfs)算直径的时候就可以把直径的一个端点“拎”起来,当做根节点

    所以我们每次算第三点的路径的时候,可以直接算(lca(p_3,p _ {max}))(p _ 3)的深度差

    (lca)倍增求吧,还方便一点点

    CODE:

    可读性不太强的样子

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    namespace yspm{
    	inline int read()
    	{
    		int res=0,f=1; char k;
    		while(!isdigit(k=getchar())) if(k=='-') f=-1;
    		while(isdigit(k)) res=res*10+k-'0',k=getchar();
    		return res*f;
    	}
    	const int N=2e5+10;
    	struct node{
    		int nxt,to;
    	}e[N<<1];
    	int head[N],cnt,n;
    	inline void add(int u,int v)
    	{
    		e[++cnt].nxt=head[u]; e[cnt].to=v;
    		return head[u]=cnt,void();
    	}
    	int fa[N][40],dep[N];
    	inline void dfs1(int x,int fat)
    	{
    		fa[x][0]=fat; dep[x]=dep[fa[x][0]]+1; 
    		for(int i=head[x];i;i=e[i].nxt)
    		{
    			int t=e[i].to; if(t==fat) continue;
    			dfs1(t,x);
    		}
    		return ;
    	}int lg[500010];
    	inline void dfs2(int x,int fat)
    	{
    		fa[x][0]=fat; dep[x]=dep[fa[x][0]]+1; 
    		for(int i=1;(1<<i)<=dep[x];++i) fa[x][i]=fa[fa[x][i-1]][i-1];
    		for(int i=head[x];i;i=e[i].nxt) if(fa[x][0]!=e[i].to) dfs2(e[i].to,x);
    		return ;
    	}
    	inline int lca(int x,int y)
    	{
    		if(dep[x]<dep[y]) swap(x,y);
    		while(dep[x]>dep[y]) x=fa[x][lg[dep[x]-dep[y]]-1];
    		if(x==y) return x;
    		for(int k=lg[dep[x]]-1; k>=0;--k) if(fa[x][k]!=fa[y][k]) x=fa[x][k],y=fa[y][k];
    		return fa[x][0];
    	}
    	
    	signed main()
    	{
    		n=read(); for(int i=1,v,u;i<n;++i) u=read(),v=read(),add(u,v),add(v,u);
    		int rt=1;  dfs1(1,0); for(int i=1;i<=n;++i) rt=dep[i]>dep[rt]?i:rt;
    		dfs1(rt,0); int ans=0,ed=1; for(int i=1;i<=n;++i) ed=dep[i]>dep[ed]?i:ed; ans+=dep[ed]-1;
    		for(int i=1;i<500010;++i) lg[i]=lg[i-1]+((1<<lg[i-1])==i);
    		dfs2(rt,0);
    		int maxx=-1,num;
    		for(int i=1;i<=n;++i)
    		{
    			if(i==ed||i==rt) continue;
    			int anc=lca(ed,i); 
    			if(maxx<dep[i]-dep[anc]) maxx=dep[i]-dep[anc],num=i;
    		} 
    		if(dep[num]==dep[rt]+1) cout<<ans<<endl;
    		else cout<<ans+maxx<<endl;
    		cout<<num<<" "<<rt<<" "<<ed<<endl;
    		return 0;
    	}
    }
    signed main(){return yspm::main();}
    

    赛后总结

    感觉好像这个(F)题一出,我就有(AK)的实力了

    但是还是不可以在打外文题的时候过度依赖翻译机

    还有要记得在循环内清空数组时能用(for)就换掉(memset)

    这俩(sb)事坑掉了我的(AK)

    加油! 冲向开学前(Rating 1650)的目标!

  • 相关阅读:
    HTML DOM教程 14HTML DOM Document 对象
    HTML DOM教程 19HTML DOM Button 对象
    HTML DOM教程 22HTML DOM Form 对象
    HTML DOM教程 16HTML DOM Area 对象
    ubuntu 11.04 问题 小结
    VC6.0的 错误解决办法 小结
    boot.img的解包与打包
    shell里 截取字符串
    从零 使用vc
    Imagemagick 对图片 大小 和 格式的 调整
  • 原文地址:https://www.cnblogs.com/yspm/p/12231658.html
Copyright © 2011-2022 走看看