• 2020ICPC·小米 网络选拔赛第一场


    2020ICPC·小米 网络选拔赛第一场

    比赛分析

    这场高手真的还是挺多的。我们队伍也实在是太拉垮了,有个队友实验未归。

    我上来切了C、I 然后就没有过题了。

    首先是J题,我的锅。我就想了几分钟就感觉是二维线段树,就直接开始写了,浪费快2hrs+,后来我突然发现我的复杂度少乘了个log,血亏。

    队友的A也调了很久,一直没有过,据他所说,他被卡傻了。

    队友2终于实验回来,做了个D,正解应该是边双还是啥的,反正他写个什么割点啥的。

    总结

    这场反正也进不了,但是暴露的问题非常多

    第一,各自蛮干非常明显,交流少了。 有想法应该先和队友交流一下,尤其是这种网络赛,多线程可敲的时候,反而不要忽视单机子的这个重要流程。像我的二维线段树,如果讲清楚,队友,或者我自己都可能看到问题,简单的dp就不会做成数据结构题

    第二,题意方面。每个人优先读一道题,然后翻译成中文,再让队友带着中文去再读一遍题意,检查是否理解错误。比如I题,我一开始读错了,队友准备写的时候,提醒了一下我,我才发现错误。以后要保证每道题目至少要被反复读过两遍。

    第三,要注意看榜单信息。如果有些题很多队过了,或者说,一些题很快被切了,那么它极大概率不是比较复杂的数据结构题,以及难的数论。。。

    第四,是勤换思路。有些时候想题目不要局限于一种算法中,要果敢放弃。思路或者题目什么时候该进行舍弃嘞?

    如果思路想不通到15min,并且此题可做,那么换思路

    如果某个题花费30min思考没有突破,先放下,去读题

    C 简单签到

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<string>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define max(a,b) (a>b ? a:b)
    #define min(a,b) (a<b ? a:b)
    #define swap(a,b) (a^=b^=a^=b)
    #define maxn 105
    #define minn -105
    #define ll long long int
    #define ull unsigned long long int
    #define uint unsigned int
    inline int read()
    {
        int ans=0;
        char last=' ',ch=getchar();
        while(ch<'0'|ch>'9')last=ch,ch=getchar();
        while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
        if(last=='-')ans=-ans;
        return ans;
    }
    int main()
    {
        string s;
        cin>>s;
        int ans=0;
        int len=s.size();
        for(int i=0;i<len;i++)
        {
            if(s[i]=='w')ans++;
            if(i)
            {
                if((s[i]=='w')&&(s[i-1]=='w'))ans++;
            }
        }
        cout<<ans<<endl;
        return 0;
    }
    
    
    

    I dfs 记忆化

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define max(a,b) (a>b ? a:b)
    #define min(a,b) (a<b ? a:b)
    #define swap(a,b) (a^=b^=a^=b)
    #define maxn 1405
    #define minn -105
    #define ll long long int
    #define ull unsigned long long int
    #define uint unsigned int
    inline int read()
    {
        int ans=0;
        char last=' ',ch=getchar();
        while(ch<'0'|ch>'9')last=ch,ch=getchar();
        while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
        if(last=='-')ans=-ans;
        return ans;
    }
    int n,m;
    
    
    char a[maxn][maxn];
    bool been[maxn][maxn];
    int out[maxn][maxn];
    
    bool dfs(int x,int y)
    {
        if(x==0||y==0||x==n+1||y==m+1)
        {
            return 1;
        }
        if(been[x][y])
        {
            return out[x][y];
        }
        been[x][y]=1;
        bool cur=0;
        if(a[x][y]=='W')cur=dfs(x-1,y);
        if(a[x][y]=='A')cur=dfs(x,y-1);
        if(a[x][y]=='S')cur=dfs(x+1,y);
        if(a[x][y]=='D')cur=dfs(x,y+1);
        out[x][y]=cur;
        return cur;
    
    }
    
    int main()
    {
        cin>>n>>m;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                cin>>a[i][j];
            }
        int ans=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                if(!been[i][j])
                {
                    dfs(i,j);
                }
                if(out[i][j]==1)ans++;
    
            }
    
    
        cout<<ans<<endl;
        return 0;
    }
    
    

    J dp

    维护二维前缀和就好了,没必要实现每次区间的维护。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define max(a,b) (a>b ? a:b)
    #define min(a,b) (a<b ? a:b)
    #define swap(a,b) (a^=b^=a^=b)
    #define maxn 1305
    #define minn -105
    #define ll long long int
    #define ull unsigned long long int
    #define uint unsigned int
    inline int read()
    {
        int ans=0;
        char last=' ',ch=getchar();
        while(ch<'0'|ch>'9')last=ch,ch=getchar();
        while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
        if(last=='-')ans=-ans;
        return ans;
    }
    int a[maxn][maxn];
    int pre[maxn][maxn];
    int give[maxn][maxn];
    int n,m,x,y;
    string ac="^_^
    ";
    string wa="QAQ
    ";
    void solve()
    {
        cin>>n>>m>>x>>y;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                a[i][j]=read();
    
            }
        int cur=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                //give[i][j]=0;
                int cur=pre[i-1][j]+pre[i][j-1]-pre[i-1][j-1];
                pre[i][j]=cur;
                cur+=pre[max(0,i-x)][max(0,j-y)]-pre[i][max(0,j-y)]-pre[max(0,i-x)][j];
                if(i>=n+2-x||j>=m+2-y)
                {
                    if(a[i][j]!=cur)
                    {
                        cout<<wa;
                        return;
                    }
                    continue;
                }
                else
                {
                    if(cur>a[i][j])
                    {
                        cout<<wa;
                        return;
                    }
                    pre[i][j]+=a[i][j]-cur;
                }
            }
        cout<<ac;
    
    }
    int main()
    {
        int _t;
        cin>>_t;
        while(_t--)solve();
        return 0;
    }
    
    

    D

    点双联通分量,预处理出每个点所属的双联通分量个数,答案为联通块数减去1加上所属的双联通块个数(预处理孤立点,所属的双联通块个数为0)

    #include<bits/stdc++.h>
    using namespace std;
    struct tedge{
    	int w,next;
    }e[1000010];
    int l[500010],dfn[500010],low[500010],st[500010],del[500010],gu[500010],d[500010];
    int cnt,tot,top,cnt1,n,m,root,sum;
    vector <int> ve[500010];
    void add(int x,int y)
    {
    	e[++cnt].w=y;
    	e[cnt].next=l[x];
    	l[x]=cnt;
    }
    void tarjan(int x)
    {
    	dfn[x]=low[x]=++tot;
    	st[++top]=x;
    	if(x==root&&l[x]==0)
    	{
    		ve[++cnt1].push_back(x);
    		gu[x]=1;
    		return;
    	}
    	for(int i=l[x];i;i=e[i].next)
    	{
    		int v=e[i].w;
    		if(!dfn[v])
    		{
    			tarjan(v);
    			low[x]=min(low[x],low[v]);
    			if(low[v]>=dfn[x])
    			{
    				cnt1++;
    				int z;
    				do{
    					z=st[top--];
    					ve[cnt1].push_back(z);
    				}while(z!=v);
    				ve[cnt1].push_back(x);
    			}
    		}
    		else
    		low[x]=min(low[x],dfn[v]);
    	}	
    }
    int main()
    {
    	cin>>n>>m;
    	int x,y;
    	for(int i=1;i<=m;i++)
    	{
    		cin>>x>>y;
    		if(x==y)
    		continue;
    		add(x,y);
    		add(y,x);
    	}
    	for(int i=1;i<=n;i++)
    	if(!dfn[i])
    	{
    		sum++;
    		root=i;
    		tarjan(i);
    	}
    	for(int i=1;i<=cnt1;i++)
        for(int j=0; j<ve[i].size();j++)
        d[ve[i][j]]++;
        for(int i=1;i<=n;i++)
        {
        	if(gu[i])
        	cout<<sum-1<<" ";
        	else
        	cout<<sum-1+d[i]<<" ";
    	}
        return 0;
    }
    

    A

    #include<bits/stdc++.h>
    using namespace std;
    const int mod=1e9+7;
    int a[300010],n,m,x;
    int f[10000010],bj[10000010],prime[10000100],tot,f1[10000010]; 
    int main()
    {
    	int n;
    	cin>>n;
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%d",&a[i]);
    		f1[a[i]]++;
    		f[a[i]]++;
    	}
    	sort(a+1,a+n+1);
    	int maxn=a[n];
    	int ans=0;
    	for(int j=2;j<=maxn;j++)
    	{
    		if(!bj[j]){
    			prime[++tot]=j;f[j]+=f[1];
    		}
    		for(int i=1;i<=tot;i++)
    		{
    			if(j*prime[i]<=maxn)
    			{
    				bj[j*prime[i]]=1;
    				f[j*prime[i]]=max(f[j*prime[i]],f1[j*prime[i]]+max(f[j],f[prime[i]]));
    			}
    			else break;
    		}
    		ans=max(ans,f[j]);
    	}
    	cout<<ans;
    	return 0;
    }
    
  • 相关阅读:
    Codeforces Round #174 (Div. 1 + Div. 2)
    Codeforces Round #176 (Div. 1 + Div. 2)
    [ARC101C] Ribbons on Tree 解题报告
    [CTS2019]珍珠 解题报告
    CF1349D Slime and Biscuits 解题报告
    [PKUWC2018]猎人杀 解题报告
    AGC047 解题报告
    肯德基 解题报告
    [GXOI/GZOI2019]旧词 解题报告
    [ARC084B] Small Multiple 解题报告
  • 原文地址:https://www.cnblogs.com/et3-tsy/p/13879472.html
Copyright © 2020-2023  润新知