2018 Multi-University Training Contest 1(solve4/12)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/passer__/article/details/81877356

1001

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6298

题意:给定一个正整数n,问是否存在三个数字x,y,z,满足n是x,y,z的倍数且x + y + z = n,若存在输出最大的x*y*z,否则输出-1

思路:将式子化简得 1 = x/n + y/n + z/n,因为n是x,y,z的倍数,所以 1 = 1 / a + 1 / b + 1 / c 求得 三组解

① 3 3 3  ② 2 4 4 ③ 2 3 6

因此当n是三的倍数的时候  3 3 3 最大  是2的倍数不是3的倍数的时候 2 4 4 最大

#include<bits/stdc++.h>
using namespace std; 
int main()
{
    int n;
    scanf("%d",&n);
    while(n--)
    {
        long long m;
        scanf("%lld",&m);   
        if(m%3==0)
        {
            long long temp=m*m*m/27;
            printf("%lld\n",temp);
        }
        else if(m%4==0)
        {
            long long temp=m*m*m/32;
            printf("%lld\n",temp);  
        } 
        else
            printf("-1\n");
    }   
    return 0;   
} 

1002

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6299

题意:给你n个括号序列,让你按照规则匹配这些序列,问你最多匹配的数量是多少

思路:我们先用栈来对每个括号字符串进行处理(代码种用力对左括号、右括号、和匹配括号数记数的办法),把匹配的括号去掉。最后出现不匹配的括号字符串只有这三种 ①(((((((      ② )))))))))((((((     ③))))))))然后我们贪心,让它最大匹配。

对于①来说肯定全部放到左边收益最大,同理③都放到右边收益最大。

那么我们考虑下②这种情况怎么最大化。对于))))((这样的来说肯定是左边放右括号多的利益最大,)))((((((((这样的肯定是右边放一个右括号多的利益最大化,不显而易见可以得到这样的想法:对于左括号比右括号多的序列,让右括号从少到多进行排序(充分利用右括号) 对于不同时满足的单独考虑 一定让左括号比右括号多的在前即可,然后对于右括号比左括号多的,那么就让左括号从大到小,尽量多的匹配,浪费最小的那个。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
struct node{
	int l;
	int r;
}no[maxn];
char s[maxn];
int cmp(node a,node b)
{
	if(a.l-a.r>=0 && b.l-b.r>=0)//左括号比右括号多 
		return a.r < b.r;//右括号从少到多
	else if(a.l-a.r>=0)//左括号比右括号多  
		return  1;
	else if(b.l-b.r>=0)//左括号比右括号多 
		return 0;
	return a.l>b.l; //右边那部分,左括号多的放前边 
} 
stack<char>S;
int main()
{
	int t,n;
	scanf("%d",&t);
	while(t--)
	{
		int ans=0;
		scanf("%d",&n);
		for(int i=0;i<n;i++)
		{
			scanf("%s",s);
			int len=strlen(s);
            for(int j=0;j<len;j++)
			{ 
				if(!S.empty())
				{
					if(s[j]==')' && S.top()=='(')
					{
						S.pop();
						ans++;
					}
					else
						S.push(s[j]);
				}
				else
					S.push(s[j]);
			}
			no[i].l=no[i].r=0;
			while(!S.empty())
			{
				if(S.top()=='(')
					no[i].l++;
				else
					no[i].r++;
				S.pop();
			}
		}
		sort(no,no+n,cmp);//神TM的贪心 
		int sum=0;
		for(int i=1;i<n;i++)
		{
			sum=sum+no[i-1].l;
			if(no[i].r>=sum)
			{
				ans+=sum;
				sum=0;
			}
			else
			{
				ans+=no[i].r;
				sum=sum-no[i].r;
			}
		}
		printf("%d\n",ans*2);
	}
	return 0;
} 

1003

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6300

题意:给了3n个点,问是否可以组成n个三角形,如果可以组成,那么输出组成的这些点的编号。题目保证三个点不共线。

思路:排个序贪心呗,按照左端点排序。

#include<bits/stdc++.h>
using namespace std;
struct node{
    int x;
    int y;
    int id;
}no[5000];
int cmp(node a,node b)
{
    if(a.x == b.x)
        return a.y < b.y;
    return a.x < b.x;
}
int main()
{
    int t,n;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=1;i<=3*n;i++)
        {
            scanf("%d%d",&no[i].x,&no[i].y);
            no[i].id=i; 
        } 
        sort(no+1,no+1+3*n,cmp);
        for(int i=1;i<=3*n;i=i+3)
        {
            printf("%d %d %d\n",no[i].id,no[i+1].id,no[i+2].id);
        }
    }
    return 0;   
} 

1004

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6301

题意:n个数和m个区间,保证m个区间之内的数不出现重复的最下字典序

思路:先将区间按照左端点排个序,从左边开始保证满足题意。然后对于一些不在区间限制范围内直接填充1,注意区间的判断和对于区间数字的回收再利用。

#include<bits/stdc++.h>
using namespace std;
struct node{
    int l;
    int r;
}no[100005];
int vis[100005];
int cmp(node a,node b)
{
    if(a.l == b.l)
        return a.r < b.r;
    return a.l < b.l;
}
priority_queue <int, vector<int>, greater<int> > q;
int main()
{
    int n,m,t;
    scanf("%d",&t);
    while(t--)
    {
        int l=1;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            q.push(i); x`x`x
        for(int i=0;i<m;i++)
            scanf("%d%d",&no[i].l,&no[i].r);
        sort(no,no+m,cmp);
        for(int i=0;i<=n;i++)
            vis[i]=0;
        while(l<no[0].l)
            vis[l++]=1;
        for(int i=0;i<m-1;i++)
        {
            if(l>no[i].r)
            {
                for(int k=no[i].l;k<=no[i+1].l-1;k++)
                    if(vis[k]!=-1)//如果标记是-1表示不在填充区 
                        q.push(vis[k]);
                continue;
            }
            for(int j=l;j<=no[i].r;j++)
            {
                vis[j]=q.top();
                q.pop();
            }
            l=no[i].r+1;
            while(l<no[i+1].l)//不在限制内 
                vis[l++]=-1;
            for(int j=no[i].l;j<=no[i+1].l-1;j++)//回收 
            {
                if(vis[j]!=-1)
                    q.push(vis[j]);
            }
        }
        for(;l<=no[m-1].r;l++)//单独处理区间 
        {
            vis[l]=q.top();
            q.pop();
        }
        while(l<=n)//最后都是1 
            vis[l++]=1;
        for(int i=1;i<=n;i++)
        {
            if(i!=1)
                printf(" ");
            printf("%d",max(vis[i],1));
        }
        printf("\n");
        while(!q.empty())
            q.pop();
    }
    return 0;
}

1007

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6304

题意:

思路:

猜你喜欢

转载自blog.csdn.net/passer__/article/details/81877356
今日推荐