2018ICPC青岛现场赛 重现训练

Posted intwentieth

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2018ICPC青岛现场赛 重现训练相关的知识,希望对你有一定的参考价值。

先贴代码,以及简要题解。

和一个队友下午双排打了一下,队友光速签到,我签的J被嫌弃写得慢以及演员。。。然后我秒出了E了思路然而难以置信这么简单的思路当时才过了十几个,于是发现D、F不是太好做。最后交了13发E才过,中间爆ll、memset超时。。赛后补了F。

只贴我写的三个题。

J: ZOJ 4067

题解:把所有0拿掉后贪心拿完前面的,然后再加上后面的最小值-1。改了三次在基佬紫帮助下才写对。

#include<cstdio>
#include<iostream>
#include<bitset>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include<cmath>
#define mp make_pair
#define pb push_back
#define ll long long
#define lc no[x].ch[0]
#define rc no[x].ch[1]
#define pa no[x].fa
#define db double
#define ls (x<<1)
#define rs (x<<1|1)
#define For(i,a,b) for(int i=a;i<=b;i++)
#define Forr(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int maxn=1e5+7;
ll a[maxn],tv;
 vector<ll>vec;
int n,m;
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&m);
		int cnt=0;
		vec.clear();
		for(int i=1;i<=n;i++)
		{
			scanf("%lld",&a[i]);
            if(a[i]==0)cnt++;
            else vec.push_back(a[i]);
		}
		m-=cnt;
		if(m<0){cout<<"Impossible
";continue;}
		if(n-cnt==m){cout<<"Richman"<<"
";continue;}
		ll ans=0;
		int pp=0;
        for(int i=0;i<(int)vec.size()&&pp<m;i++)
        {
            ans+=vec[i];
            pp++;
        }
        ll minn=1e9+1;
		for(int i=m;i<(int)vec.size();i++)
        {
            minn=min(minn,vec[i]);
        }
        ans+=minn-1;
		cout<<ans<<"
";
	}
}

 E:ZOJ 4062

题解:二分答案,可以看出这个过程可以谈心,就是尽可能少的走回头路,check时优先满足当前这个格子的高度,然后一路做过去,要特判n-1的情况,因为这样如果n满足了就不需要走过去了。我写的偏复杂了,一开始记录每个点的高度,然后直接爆了ll,完全发现不了,写法太丑陋了,换了种写法继续TLE,,memset真棒。

#include<cstdio>
#include<iostream>
#include<bitset>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include<cmath>
#define mp make_pair
#define pb push_back
#define ll long long
#define lc no[x].ch[0]
#define rc no[x].ch[1]
#define pa no[x].fa
#define db double
#define ls (x<<1)
#define rs (x<<1|1)
#define For(i,a,b) for(int i=a;i<=b;i++)
#define Forr(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int maxn=2e5+7;
ll a[maxn],tv;
ll n,m;
ll cnt;
ll pq[maxn];
bool check(ll x)
{
    for(int i=1;i<=n;i++)pq[i]=0;
    ll fq=m;
    fq--;
    pq[1]++;
    for(int i=1;i<=n;i++)
    {
        if(fq<0)return false ;
        ll tmp=(x+a[i]-1)/a[i];
        if((pq[i])>=tmp&&i<n)
        {
            fq--;pq[i+1]++;continue;
        }
        else if((pq[i])>=tmp&&i==n)
        {
            continue;
        }
       // if(x==5)cout<<pq[i]<<"  "<<i<<" "<<fq<<endl;
        pq[i+1]=tmp-pq[i];
        ll vq=tmp-pq[i];
        if(i==n)fq-=(vq)*2;
       else if(i==n-1)
        {
            fq-=(vq*2);
            if(pq[n]>=(x+a[n]-1)/a[n])continue;
            else pq[n]++,fq--;
        }
        else pq[i+1]++,fq-=(vq*2+1);
    }// if(x==5)cout<<fq<<"
";
    if(fq>=0)return true;
    else return false;
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
        scanf("%lld%lld",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&a[i]);
        }
        ll ans=0ll;
        ll l=1ll,r=1e18;
        while(l<=r)
        {
            ll mid=(l+r)>>1;
            if(check(mid))l=mid+1,ans=mid;
            else r=mid-1; //cout<<l<<" "<<r<<" "<<mid<<" "<<ans<<"
";
        }
        printf("%lld
",ans);
	}
}

 F:ZOJ 4063

题解:当时现场赛的队伍说有很多构造题,于是我天真的觉得这应该是个构造题,然后发现自己无从下手,就中期怼E去了,然后晚上发现D不会做,就继续想,瞄了眼题解说打表找规律。然后打了20分钟的表成功打出,于是找规律,发现就是对于当前第i行,是以lowbit(i)*2的长度分段的,以上一行按照这个长度进行中心旋转得到的,然后什么时候不行呢,疯狂枚举发现,当m>=lowbit(n)时不成立。因此就打表预处理然后输出就好了。

打表代码:

#include<cstdio>
#include<iostream>
#include<bitset>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include<cmath>
#define mp make_pair
#define pb push_back
#define ll long long
#define lc no[x].ch[0]
#define rc no[x].ch[1]
#define pa no[x].fa
#define db double
#define ls (x<<1)
#define rs (x<<1|1)
#define For(i,a,b) for(int i=a;i<=b;i++)
#define Forr(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int maxn=1e5+7;
int a[200][200];
int vis[200][200];
int pan[200];
vector<int >vec[maxn];
int main()
{
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=20;i++)a[0][i]=i,vis[i][i]=1;
    for(int i=1;i<=20;i++)
    {
        memset(pan,0,sizeof(pan));
        for(int j=1;j<=20;j++)
        {
            if(!a[i][j])
            for(int k=1;k<=20;k++)
            {
                if(!vis[j][k]&&j!=k&&!pan[k])
                {
                    int flag=0,fla=0;
                    for(int pp=1;pp<i;pp++)
                    {
                        if(vis[j][a[pp][j]]&&vis[k][a[pp][k]]&&!vis[a[pp][k]][a[pp][j]])
                        {
                            vis[j][k]=vis[a[pp][k]][a[pp][j]]=vis[k][j]=vis[a[pp][j]][a[pp][k]]=1;
                            a[i][j]=k;a[i][k]=j;a[i][a[pp][k]]=a[pp][j];a[i][a[pp][j]]=a[pp][k];pan[k]=pan[j]=pan[a[pp][j]]=pan[a[pp][k]]=1;
                            flag=1;
                            break;
                        }
                        if(vis[j][a[pp][j]]&&vis[k][a[pp][k]])fla=1;

                    }
                    if(flag)
                    {break;}
                    if(!fla)
                    {
                        a[i][j]=k;a[i][k]=j;pan[k]=pan[j]=1;vis[j][k]=vis[k][j]=1;break;
                    }
                }
            }
        }
    }
    for(int i=0;i<=15;i++)
    {
        for(int j=1;j<=15;j++)
        {
            cout<<a[i][j]<<(j==15?‘
‘:‘ ‘);
        }
    }
}

  AC代码:

#include<cstdio>
#include<iostream>
#include<bitset>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include<cmath>
#define mp make_pair
#define pb push_back
#define ll long long
#define lc no[x].ch[0]
#define rc no[x].ch[1]
#define pa no[x].fa
#define db double
#define ls x<<1
#define rs x<<1|1
#define For(i,a,b) for(int i=a;i<=b;i++)
#define Forr(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int maxn=1005;
int a[maxn][maxn];
int lowbit(int x){return x&(-x);}
void cal()
{
    for(int i=1;i<=1001;i++)a[0][i]=i;
    for(int i=1;i<=1001;i++)
    {
        int kk=lowbit(i);int pp=kk*2;
        for(int j=1;j<=1001;j+=pp)
        {
            for(int k=0;k<pp;k++)
            {
                a[i][j+k]=a[i-1][pp+j-k-1];
            }
        }
    }
 /*   for(int i=1;i<=20;i++)
    {
        for(int j=1;j<=20;j++)
        {
            cout<<a[i][j]<<(j==20?"
":" ");
        }
    }*/
}

int main()
{
    cal();
    int t;
    scanf("%d",&t);
    int n,m;
    while(t--)
    {
        scanf("%d%d",&n,&m);
        if(m>=lowbit(n)){cout<<"Impossible
";continue;}
        for(int i=1;i<=m;i++)
        {
            for(int j=1;j<=n;j++)
            {
                cout<<a[i][j]<<(j==n?"
":" ");
            }
        }
    }

}

  

 

以上是关于2018ICPC青岛现场赛 重现训练的主要内容,如果未能解决你的问题,请参考以下文章

2018 ACM-ICPC 青岛站现场赛总结

ACM-ICPC 2018 青岛赛区现场赛 K. Airdrop && ZOJ 4068 (暴力)

ACM-ICPC 2018 青岛赛区现场赛 D. Magic Multiplication && ZOJ 4061 (思维+构造)

青岛 2016ICPC 区域现场赛题目

2016ACM/ICPC亚洲区大连站现场赛题解报告

2016ACM/ICPC亚洲区大连站现场赛题解报告