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;
}