zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    Codeforces 1291 Round #616 (Div. 2) B
    总结
    刷新DNS解析缓存+追踪+域名解析命令
    数学--数论--Hdu 5793 A Boring Question (打表+逆元)
    Lucene.net(4.8.0) 学习问题记录六:Lucene 的索引系统和搜索过程分析
    LeetCode 117 Populating Next Right Pointers in Each Node II
    LeetCode 116 Populating Next Right Pointers in Each Node
    test test
    LeetCode 115 Distinct Subsequences
    LeetCode 114. Flatten Binary Tree to Linked List
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10779896.html
Copyright © 2011-2022 走看看