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
题意:
思路: