A题
给出n,求xyz的最大值,要求n = x + y + z 且 n 能整除x y z,没有输出-1
解:1 = 1/3 + 1/3 + 1/3 = 1/2 + 1/4 + 1/4,只要能被3/4整除就有解
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll T,n;
int main()
{
scanf("%lld",&T);
while(T--)
{
scanf("%lld",&n);
if(n % 3 == 0) printf("%lld\n",(n / 3) * (n / 3) * (n / 3));
else if(n % 4 == 0) printf("%lld\n",(n / 2) * (n / 4) * (n / 4));
else printf("-1\n");
}
return 0;
}
B题 给你n个括号字符串,排序这些括号字符串,怎么排序能使其配对最多并输出总共有几个括号可以参与配对
解:预处理每个字符串,计算出每个字符串本身可以配对几个,有几个'('和')'还没进行配对(栈)
排序(谁能对形成配对的贡献大,字符串里 '(' 出现次数比 ')'多,它比较适合排前面,能够使自己对整个配对做出的贡献最大,a和b比较的话,如果a和b都是'('贡献大的话,谁的')'小就排前面,因为相对来说')'的要往后排,相对贡献会大一些)
D题
构造一个序列,使得m个给定区间内的数字各不相同并且序列的字典序最小
解:区间位置有相离,相交,重合3种
先将区间按左端点排个序
重合不需要考虑,因为满足大区间的也满足小区间
相交:前一个区间先选,后一个区间的数字从不重合部分开始,依次选重合区间没有选过的数字
#include<bits/stdc++.h>
using namespace std;
struct node
{
int l,r;
}a[100010];
int T,n,m,k,l,r;
int ans[100010],num[100010];
bool cmp(node k,node p)
{
if(k.l == p.l) return k.r > p.r;
return k.l < p.l;
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
memset(ans,0,sizeof(ans));
memset(num,0,sizeof(num));
for(int i = 0;i < m; ++i) scanf("%d%d",&a[i].l,&a[i].r);
sort(a,a + m,cmp);
for(int j = a[0].l;j <= a[0].r; j++)
ans[j] = j - a[0].l + 1;
l = a[0].l;
r = a[0].r;
for(int i = 1;i < m; ++i)
{
if(r >= a[i].r) continue;
k = 1;
if(a[i].l <= r) //相交区间
{
for(int j = a[i].l;j <= r; ++j)
num[ans[j]] = i;
for(int j = r + 1;j <= a[i].r; ++j)
{
while(num[k] == i) ++k;
ans[j] = k++;
}
}
else //不相交区间
for(int j = a[i].l;j <= a[i].r; ++j)
ans[j] = k++;
l = a[i].l;
r = a[i].r;
}
for(int i = 1;i <= n; ++i)
{
if(i > 1) printf(" ");
if(ans[i]) printf("%d",ans[i]);
else printf("1");
}
printf("\n");
}
return 0;
}
ps:正解:利用set的去重和排序功能,利用tot标记一下当前可入set的左界(可重复利用),pre数组记录的是区间左界
#include<bits/stdc++.h>
using namespace std;
int T,n,m,l,r,tot;
set<int>s;
int ans[100100],pre[100100];
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i = 1;i <= n; ++i) pre[i] = i,s.insert(i);
for(int i = 0;i < m; ++i)
{
scanf("%d%d",&l,&r);
pre[r] = min(pre[r],l);
}
for(int i = n - 1;i >= 1; --i)
pre[i] = min(pre[i],pre[i + 1]);
tot = 1;
for(int i = 1;i <= n; ++i)
{
while(tot < pre[i]) s.insert(ans[tot++]);
ans[i] = *s.begin();
s.erase(ans[i]);
}
for(int i = 1;i < n; ++i)
printf("%d ",ans[i]);
printf("%d\n",ans[n]);
}
return 0;
}
K题
给出西八区的时间,求其他时区的时间
解:极度玄学...咱也不知道为啥错...咱也不知道改了哪里就对了
教训:避免浮点数的加减,全部换算成分钟
#include<bits/stdc++.h>
using namespace std;
int T,n,m,len;
string s;
double t,f;
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d UTC%lf",&n,&m,&t);
int k = n * 60 + m - 8 * 60;
int p = t * 10;
k += p * 6;
while(k < 0) k += 24 * 60;
k %= (24 * 60);
m = k % 60;
n = k / 60;
printf("%02d:%02d\n",n,m);
}
return 0;
}