zoukankan      html  css  js  c++  java
  • NIKKEI Programming Contest 2019 翻车记

      A:签到。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
    	int x=0,f=1;char c=getchar();
    	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    	return x*f;
    }
    int n,a,b;
    int main()
    {
    	/*freopen("a.in","r",stdin);
    	freopen("a.out","w",stdout);*/
    	n=read(),a=read(),b=read();
    	cout<<min(a,b)<<' '<<max(0,a+b-n);
    	return 0;
    }
    

      B:签到。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
    	int x=0,f=1;char c=getchar();
    	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    	return x*f;
    }
    #define N 110
    int n;
    char a[N],b[N],c[N];
    int main()
    {
    	/*freopen("a.in","r",stdin);
    	freopen("a.out","w",stdout);*/
    	n=read();
    	scanf("%s",a+1);scanf("%s",b+1);scanf("%s",c+1);
    	int ans=0;
    	for (int i=1;i<=n;i++)
    	{
    		if (a[i]==b[i]&&b[i]==c[i]) ;
    		else if (a[i]==b[i]||a[i]==c[i]||b[i]==c[i]) ans++;
    		else ans+=2;
    	}
    	cout<<ans;
    	return 0;
    }
    

      C:考虑一种菜自己吃和对方吃的收益差,于是显然按ai+bi排序从大到小选即可。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
    	int x=0,f=1;char c=getchar();
    	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    	return x*f;
    }
    #define N 300010
    #define ll long long
    int n;
    struct data
    {
    	int x,y;
    	bool operator <(const data&a) const
    	{
    		return x+y<a.x+a.y;
    	}
    }a[N];
    ll ans;
    int main()
    {
    	/*freopen("a.in","r",stdin);
    	freopen("a.out","w",stdout);*/
    	n=read();
    	for (int i=1;i<=n;i++) a[i].x=read(),a[i].y=read();
    	sort(a+1,a+n+1);reverse(a+1,a+n+1);
    	for (int i=1;i<=n;i++)
    	if (i&1) ans+=a[i].x;
    	else ans-=a[i].y;
    	cout<<ans;
    	return 0;
    }

      D:显然图仍是一个DAG,其中度数为0的点是原树的根。由于图中没有重边,瞎考虑一下容易发现,对于每一个点,由根到它的最长路上该点的前驱即为其在原树中的父亲。拓扑排序一下即可。开始写了个不知道啥玩意于是比E晚了10min。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
    	int x=0,f=1;char c=getchar();
    	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    	return x*f;
    }
    #define N 300010
    #define ll long long
    int n,m,p[N],fa[N],deep[N],degree[N],q[N],t,root;
    bool flag[N];
    struct data{int to,nxt;
    }edge[N];
    void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
    void topsort()
    {
    	int head=0,tail=0;
    	for (int i=1;i<=n;i++) if (!degree[i]) q[++tail]=i;
    	while (tail<n)
    	{
    		int x=q[++head];
    		for (int i=p[x];i;i=edge[i].nxt)
    		{
    			degree[edge[i].to]--;
    			if (deep[x]+1>deep[edge[i].to])
    			{
    				deep[edge[i].to]=deep[x]+1;
    				fa[edge[i].to]=x;
    			}
    			if (!degree[edge[i].to]) q[++tail]=edge[i].to;
    		}
    	}
    }
    int main()
    {
    	n=read(),m=read();
    	for (int i=1;i<n+m;i++)
    	{
    		int x=read(),y=read();
    		addedge(x,y);degree[y]++;
    	}
    	topsort();
    	for (int i=1;i<=n;i++) printf("%d
    ",fa[i]);
    	return 0;
    }
     

      E:显然从大到小考虑每条边是否需要删即可,但删边的过程中难以维护连通块信息。注意到只有MST的边会对最后所得图的连通性产生影响。于是求出MST,然后可以从大到小删边用LCT维护,但这样显然比较毒瘤。事实上还可以建出kruskal重构树,从大到小考虑每条边,如果其在重构树的父亲不需要被删掉,显然其也不需要被删掉;否则此时其所在连通块即为其在重构树上的子树,判断一下是否需要删掉即可。这样就得到了最后的连通信息,最后再考虑每条边是否保留即可。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
    	int x=0,f=1;char c=getchar();
    	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    	return x*f;
    }
    #define N 400010
    #define ll long long
    int n,m,a[N],fa[N],id[N],cnt,ans;
    bool isdel[N],flag[N];
    ll value[N<<2];
    struct data
    {
    	int x,y,z;
    	bool operator <(const data&a) const
    	{
    		return z<a.z;
    	}
    }e[N];
    int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
    namespace kruskal_tree
    {
    	int p[N<<2],t,degree[N<<2],fa[N<<2];
    	ll size[N<<2];
    	struct data{int to,nxt;}edge[N<<2];
    	void addedge(int x,int y){t++;degree[y]++;fa[y]=x;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
    	void link(int x,int y,int i)
    	{
    		id[i]=++cnt;addedge(cnt,x),addedge(cnt,y);
    	}
    	void dfs(int k)
    	{
    		size[k]=a[k];
    		for (int i=p[k];i;i=edge[i].nxt)
    		{
    			dfs(edge[i].to);
    			size[k]+=size[edge[i].to];
    		}
    	}
    	void build()
    	{
    		for (int i=1;i<=cnt;i++)
    		if (!degree[i]) dfs(i);
    	}
    	void del()
    	{	
    		isdel[0]=1;
    		for (int i=m;i>=1;i--)
    		if (flag[i]&&isdel[fa[id[i]]]&&e[i].z>size[id[i]]) isdel[id[i]]=1;
    	}
    }
    void dfs(int k)
    {
    	for (int i=kruskal_tree::p[k];i;i=kruskal_tree::edge[i].nxt)
    	{
    		dfs(kruskal_tree::edge[i].to);
    		if (!isdel[k]) fa[find(kruskal_tree::edge[i].to)]=k;
    	}
    }
    int main()
    {
    	n=read(),m=read();
    	for (int i=1;i<=n;i++) a[i]=read();
    	for (int i=1;i<=m;i++) e[i].x=read(),e[i].y=read(),e[i].z=read();
    	sort(e+1,e+m+1);
    	for (int i=1;i<=4*n;i++) fa[i]=i;cnt=n;
    	for (int i=1;i<=m;i++)
    	{
    		int p=find(e[i].x),q=find(e[i].y);
    		if (p!=q) kruskal_tree::link(p,q,i),fa[p]=fa[q]=id[i],flag[i]=1;
    	}
    	kruskal_tree::build();
    	kruskal_tree::del();
    	for (int i=1;i<=cnt;i++) fa[i]=i;
    	for (int i=1;i<=cnt;i++)
    	if (!kruskal_tree::degree[i]) dfs(i);
    	for (int i=1;i<=m;i++)
    	if (find(e[i].x)==find(e[i].y)&&kruskal_tree::size[find(e[i].x)]>=e[i].z) ans++;
    	cout<<m-ans;
    	return 0;
    }

      result:rank 132 rating +84

  • 相关阅读:
    docker的安装
    Linux的常用命令
    HTTP协议,HTTPS协议,Websocket协议
    常用排序
    go的数组,切片,map
    if-else,switch,for循环
    go的函数,包以及mode的补充
    Android学习笔记——从源码看Handler的处理机制
    ElementUI
    关于IO的理解
  • 原文地址:https://www.cnblogs.com/Gloid/p/10328307.html
Copyright © 2011-2022 走看看