• Codeforces Round #552 Div. 3


    题目链接:戳我

    前两题是littlesun_wl小可爱写的qwqwq

    A

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #define MAXN 100010
    #define INF 0x3f3f3f3f
    using namespace std;
    int a[MAXN];
    int main()
    {
    	for(int i=1;i<=4;i++)
    	{
    		scanf("%d",&a[i]);
    	}
    	sort(a,a+5);
    	int x=(a[1]+a[2]-a[3])/2;
    	int y=(a[2]+a[3]-a[1])/2;
    	int z=(a[1]+a[3]-a[2])/2;
    	printf("%d %d %d",x,y,z);
    	return 0;
     } 
    

    B

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #define MAXN 1000
    #define INF 0x3f3f3f3f
    using namespace std;
    int G[MAXN];
    int sign[MAXN];
    int cnt;
    int main()
    {
    	int n;
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%d",&G[i]);
    	}
    	int mx=0;int mn=INF;
    	for(int i=1;i<=n;i++)
    	{
    		sign[G[i]]++;
    		mx=max(mx,G[i]);
    		mn=min(mn,G[i]);
    	}
    	int k1=(mx-mn)/2;
    	int k2=mx-mn;
    //	printf("mn=%d,mx=%d,k=%d",mn,mx,k);
    	int num;
    	for(int i=1;i<=100;i++)
    	{
    		if(sign[i]!=0) cnt++;
    		if(G[i]!=mx&&G[i]!=mn&&G[i]!=0) num=G[i];
    		
    	}
    //	printf("%d",cnt);
    	if(n==1||cnt==1)
    	{
    		printf("0");
    		return 0;
    	}
    	if(cnt!=2&&cnt!=3)
    	{
    		printf("-1");
    		return 0;
    	}
    	else if(cnt==2)
    	{
    		if(k2%2==0)
    		{
    			printf("%d",k1);
    			return 0;
    		}
    		else
    		{
    			printf("%d",k2);
    			return 0;
    		}
    		
    	}
    	else if(cnt==3)
    	{
    		int a=mn+k1;
    //		printf("a=%d",a);
    		if(a==num&&k2%2==0)
    		{
    			printf("%d",k1);
    			return 0;
    		}
    		else
    		{
    			printf("-1");
    			return 0;
    		}
    	}
    	return 0;
    }
    

    C

    算出来有多少循环,然后处理一下边上的特殊情况即可。

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<cstdio>
    #define MAXN 1000010
    using namespace std;
    typedef long long ll;
    const int INF=1e9+71017;
    int n,ans,a[3];
    int p[7]={0,0,1,2,0,2,1};
    int c[3]={3,2,2};
    int g[3];
    int getans(int k)
    {
    	int t=INF;
    	for(int i=0;i<3;i++) g[i]=a[i],t=min(t,a[i]/c[i]);
    	for(int i=0;i<3;i++) g[i]-=c[i]*t;
    	t=t*7;
    	for(int i=k;i!=(k+6)%7;i=(i+1)%7)
    	{
    		if(!g[p[i]]) break;
    		else t++,g[p[i]]--;
    	}
    	return t;
    }
    int main()
    {
    	#ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d%d%d",&a[0],&a[1],&a[2]);
    	for(int i=0;i<7;i++)
    		ans=max(ans,getans(i));
    	printf("%d
    ",ans);
    	return 0; 
    }
    

    D

    贪心
    如果没有日光,显然是要先用能被恢复的。
    如果有日光,分类讨论一下能被恢复的是否到达上限即可。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define MAXN 200010
    int n,a,b,ans;
    int p[MAXN];
    int main()
    {
    	#ifndef ONLINE_JUDGE
    	freopen("ce.in","r",stdin);
    	#endif
    	scanf("%d%d%d",&n,&a,&b);
        int aa=a,bb=b;
        for(int i=1;i<=n;i++) scanf("%d",&p[i]);
        for(int i=1;i<=n;i++)
        {
            if(a==0&&b==0) break;
            if(p[i]==0)
            {
                if(b) b--;
                else a--;
            }
            else
            {
                if(b<bb)
                {
                    if(a) a--,b++;
                    else b--;
                } 
                else
                {
                    if(b) b--;
                    else a--;
                }
            }
            ans=i;
        }
        printf("%d
    ",ans);
    	return 0;
    }
    

    E

    两个人在一个序列中交替选择,每次从值最大的位置开始选,左右分别拓展,拓展K位(如果没有的话就停止)。每次选择完之后序列会去掉选择的人。问最后原序列上每个位置的人是被谁选择的。
    emmmm 上届为(n^2)的暴力当然是很好打的啦,如何优化复杂度呢?每次选择完之后,记录一下l,r两个数组,表示选择的人的左右区间,最右边的位置的l为最左边的位置,最左边的位置的r为最右边的位置。这样左右拓展K位的时候就可以避免重复访问已经选择过的人啦!

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #define MAXN 400010
    using namespace std;
    int n,cnt,maxx,k,op=1;
    int a[MAXN],l[MAXN],r[MAXN],c[MAXN];
    struct Node
    {   
        int pos,sum;
        friend bool operator < (Node x,Node y){return x.sum<y.sum;}
    };
    priority_queue<Node>q;
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++) 
            scanf("%d",&a[i]),l[i]=r[i]=i,q.push((Node){i,a[i]});
        maxx=n;
        while(!q.empty())
        {
            int cur_pos=q.top().pos;
            c[cur_pos]=op;
            int ll=cur_pos-1;
            for(int i=1;i<=k;i++)
            {
                while(c[ll]&&ll>0) ll=l[ll]-1;
                if(ll<=0) break;
                c[ll]=op;
            }
            int rr=cur_pos+1;
            for(int i=1;i<=k;i++)
            {
                while(c[rr]&&rr<=n) rr=r[rr]+1;
                if(rr<=0) break;
                c[rr]=op;
            }
            r[ll]=rr;
            l[rr]=ll;
            op=3-op;
            while(!q.empty())
            {
                if(c[q.top().pos])q.pop();
                else break;
            }
        }
        for(int i=1;i<=n;i++) printf("%d",c[i]);puts("");
        return 0;
    }
    

    F

    题意是给你一些东西,每个东西都有价值。还有一些优惠条件,形式为“每买n个物品,前m便宜的物品免费”。问如果买k个东西,最少需要多少钱?
    因为涉及到前m便宜的东西免费,所以肯定要先从小到大排序。然后我们从小到大取,用优惠条件去凑k个。
    这时候。。。就想到了动态规划。
    我们设(dp[i])表示排序之后,买i件物品最少需要多少钱。然后记录一个前缀和。
    因为k比较小,所以我们只要开一个桶,(pay[i])表示买i个东西,最多可以免费的物品个数。
    然后(k^2)转移即可。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    using namespace std;
    #define MAXN 200010
    int n,m,k;
    int sum[MAXN],cost[MAXN],pay[MAXN],dp[MAXN];
    int main()
    {
    	#ifndef ONLINE_JUDGE
    	freopen("ce.in","r",stdin);
    	#endif
    	scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=n;i++) scanf("%d",&cost[i]);
        for(int i=1;i<=m;i++) 
        {
            int cur1,cur2;
            scanf("%d%d",&cur1,&cur2);
            if(cur1>k) continue;
            if(pay[cur1]&&cur2>pay[cur1]) pay[cur1]=cur2;
            if(pay[cur1]==0) pay[cur1]=cur2; 
        }
        sort(&cost[1],&cost[n+1]);
        for(int i=1;i<=n;i++) sum[i]=sum[i-1]+cost[i];
        memset(dp,0x3f,sizeof(dp));
        dp[0]=0;
        for(int i=0;i<=k;i++)
        {
            for(int j=1;j<=k;j++)
            {
                if(pay[j]==0) continue;
                dp[i+j]=min(dp[i+j],dp[i]+sum[i+j]-sum[i+pay[j]]);
            }
            dp[i+1]=min(dp[i+1],dp[i]+sum[i+1]-sum[i]);
        }
        printf("%d
    ",dp[k]);
    	return 0;
    }
    

    G

    题意是给你一些数,求两个位置,使得这两个位置上面的数的LCM全局最小。
    因为LCM是两个数的乘积除以GCD,所以我们考虑枚举GCD,开一个桶记录每个数出现的位置,从GCD向上一路查询,找最小的前两个即可。
    怎么说呢,一般这个数据范围都是枚举约数的做法吧!

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<cstdio>
    #define MAXN 1000010
    using namespace std;
    int n,pos1,pos2;
    int a[MAXN],pos[10000010];
    long long ans=0x3f3f3f3f3f3f3f3f;
    int main()
    {
    	#ifndef ONLINE_JUDGE
    	freopen("ce.in","r",stdin);
    	#endif
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%d",&a[i]);
    		if(pos[a[i]])
    		{
    			if(a[i]<ans)
    				ans=1ll*a[i],pos1=pos[a[i]],pos2=i;
    		}
    		else pos[a[i]]=i;
    	}
    	for(int i=1;i<=10000000;i++)
    	{
    		if(i>ans) break;
    		int ll=0;
    		for(int j=i;j<=10000000;j+=i)
    		{
    			if(pos[j]==0) continue;
    			if(!ll) ll=j;
    			else
    			{
    				long long cur_ans=1ll*j*ll/i;
    				if(cur_ans<ans) 
    				{ans=cur_ans,pos1=pos[ll],pos2=pos[j];break;}
    			}
    			
    		}
    	}
    	if(pos1>pos2) swap(pos1,pos2);
    		printf("%d %d
    ",pos1,pos2);
    	return 0;
    }
    
  • 相关阅读:
    【解题报告】 [YNOI2019]排队
    【解题报告】[AHOI2001]彩票摇奖
    【解题报告】 [NOIP2006]能量项链
    【解题报告】 启示录
    【解题报告】 【NOIP2018】 摆渡车
    【解题报告】 【NOIP2017】 奶酪
    C# winform 窗体从右下角向上弹出窗口效果
    C#开发COM+组件和ActiveX控件
    JQuery
    How to delete a team project from Team Foundation Service (tfs.visualstudio.com)
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10779896.html
Copyright © 2020-2023  润新知