博主有了一群边缘OB翻译者,做题顺利了好多,这次提供翻译啦(感谢OB们
翻译:
A:输入一个数n,接下来n行:每行两个数li ri,代表当前情况下节点i的前驱和后继,没有则为0;求一种连法使得其形成1整条链表,其中只出现1~n,输出n行,每行两个数li ri,代表节点i的前驱和后继
B:Ivan有一个长度为n的、元素为各不相同的整数的数组,他决定使用Merge Sort,所以他决定将所有元素拆成多个递增的数列,求最少数列分法,输出时每行一个数列
C:给予你2个数n,k,要求你使用n对括号使得其权值和为k
*对于一对括号(),其权值为其外包裹它的()个数
输出合法的括号序列,若无正解,输出Impossible
补充:C题的样例解释:
1、 3对括号得到1,输出()(()),和为0+0+1
2、 4对括号得到6,输出(((()))),和为0+1+2+3
3、 2对括号得到5,无法得到正确的答案,所以输出Impossible
D:求狗最多吃的食物碗数。
输入:第一行2个数n,T,T代表狗有T的时间吃,第T秒时狗将不能吃东西。
第二行n个数ti,表示第i碗食物将在ti时冷却。
狗将从初始位置0开始,第i碗食物在i的位置,狗需要消耗1秒从x跑向x+1,对于第i碗食物,有:
若到达时时间已经>=ti,则狗将直接吃掉食物并跑向右侧的碗
若到达时间<ti,则狗有2个选择:等待到ti吃掉这碗食物再跑向下一个碗,或者选择直接跑向下一个碗;
若狗在T前跑过n个碗,则时间直接结束。
E:对于一个1*N的空间内,每个格子上可能有一只Packman、或一颗豆子,或什么都没有。Packman每个时间点都可以向任意方向移动一格并吃掉这格上的豆子(如果有的话),同一时间内同一格上可以有任意只数Packman朝向任意方向;求最短时间使得所有豆子被吃光并输出这个时间
F题:有n个候选人竞争k个位置,其中有m个给他们投票的人,每个人最后的排名按照他们的得票数从高到低排列,如果有两个人得票数量相同,则按照最后投给他票的人投票时间从早到晚进行排列
前k个人可以入选,然后现在有a个人已经投票 你需要对每个人进行判断:后面的m-a个人投完票以后若他一定能入选,输出1,若他有可能入选 输出2,若他不能入选,输出3
样例:第一行分别是nkma
下面一行a个数表示前a个人投给了谁
G:sb题请看样例自行理解。
H:给数列中的数加总和尽量少的数字使其先递增后递减(光增也资瓷)
J:
学生间要送礼物,对于一个学生,ta只会向他认识的学生送礼物。
输入:第一行n,m,接下来m行每行2个数xi,yi,表示xi,yi中间已经认识;如果xi,yi出现过,仍会出现yi,xi
输出:第一行一个数x,是最倒霉的学生送出的礼物个数,要求这个x尽可能小.(spj,满足x正确的情况下任意解均可)
接下来m行,每行2个数x,y,表示x要向y送1个礼物
补充:最倒霉的学生是送出礼物最多的学生
K:
给定n次条乘车路线,每次从地点a->地点b,乘车路线按时间给出(即要按顺序处理)
每次乘车要花费a 当第i+1条路线的起点与第i条的终点重合时,可以选择换乘,则花费降为b
还可以购买不超过k张旅行卡,使得在两站之间的往返不需要花费.
求跑完所有路线的最小花费,注意区分大小写
L题,给定一颗有N个点的树,对于每个节点,已知由它发出的每条边连接哪些节点,要求复原这颗树
M题给一个数列,判断是不是等差数列,输出下一项
题解:
博主只做了其中的6道水题,多多海涵
A题代码:
#include <cstdio>
#include <iostream>
using namespace std;
int n,i,pre[105],nxt[105],kq[105],num;
int main()
{
scanf("%d",&n);
for (i=1;i<=n;i++)
{
scanf("%d%d",&pre[i],&nxt[i]);
if (pre[i]==0) kq[++num]=i;
}
for (i=1;pre[i];i=pre[i]);
int ll=i;
for (i=ll;num;i=nxt[i])
if (nxt[i]==0)
{
if (kq[num]==ll) num--;
if (num) nxt[i]=kq[num],pre[kq[num]]=i,num--;
}
for (i=1;i<=n;i++)
printf("%d %d\n",pre[i],nxt[i]);
}
啊这个B题有必要说一下,毕竟naive的博主一开始使用了n^2logn的愚蠢子序列做法,但是其实可以nlogn的,这里使用了vector,因为ta既然已经新增加了一个序列,这个数字一定小于上一个序列的最大值啊(上一个序列里的最大值是所有序列最大值中最小的!maxx递减啊)。如果ta不小于的话,由于maxx数组是递减的,我们就可以二分出ta在哪个组里啦
B题代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
int a[200005],g[200005],maxx[200005];
vector<int>q[200005];
bool c[200005];
void stupid()
{
int n,i,j;int maxx=0,lj=0;
scanf("%d",&n);
lj=n;
for (i=1;i<=n;i++) scanf("%d",&a[i]);
for (i=1;lj && i<=n;i++)
if (!c[i])
{
for (j=1;j<=maxx;j++) g[j]=0;
maxx=0;
for (j=i;lj && j<=n;j++)
if (!c[j])
{
int l=1,r=maxx;
while (l<=r)
{
int mid=(l+r)>>1;
if (g[mid]>a[j]) r=mid-1;
else l=mid+1;
}
if (maxx<r+1)
maxx=r+1,g[r+1]=a[j],printf("%d ",a[j]),c[j]=true,lj--;
}
printf("\n");
}
}
int main()
{
int n,i,j;
scanf("%d",&n);
for (i=1;i<=n;i++) scanf("%d",&a[i]);
int zu=1;maxx[zu]=a[1];q[zu].push_back(a[1]);
for (i=2;i<=n;i++)
if (maxx[zu]>a[i])
{
maxx[++zu]=a[i];
q[zu].push_back(a[i]);
}
else
{
int l=1,r=zu;
while (l<=r)
{
int mid=(l+r)>>1;
if (maxx[mid]<a[i]) r=mid-1;
else l=mid+1;
}
maxx[r+1]=a[i];
q[r+1].push_back(a[i]);
}
for (i=1;i<=zu;i++)
{
for (j=0;j<q[i].size();j++) printf("%d ",q[i][j]);
printf("\n");
}
}
C题代码:
#include <cstdio>
using namespace std;
long long k;
int main()
{
long long n;
scanf("%I64d%I64d",&n,&k);
if (n*(n-1)/2<k){printf("Impossible"); return 0;}
long long cnt=1;
while (k)
{
if (cnt-1<=k)
{
printf("(");
k-=cnt-1;
cnt++; n--;
}
else{printf(")"); cnt--;}
}
while (cnt!=1) printf(")"),cnt--;
while (n) printf("()"),n--;
}
D题还是很有意思的:
为什么我只寻找最大的等饭时间?因为我等了ta其他的饭都等完了。即使ta在一些小时间的后面,我等小时间也相当于等着大时间啊(其他详见注释
#include <cstdio>
#include <queue>
#include <iostream>
using namespace std;
priority_queue <int> q;
int main()
{
int n,T;
scanf("%d%d",&n,&T);
int x,tp=T-1,dl=0,ans=0;//tp=T-1:还有从0-1的时间
for (int i=1;i<=min(n,T-1);i++)
{
tp--;//还剩下多少时间,每次减去的时间用来奔跑,放在开始就减的目的:第t时间你就不能吃了哦
while (!q.empty() && q.top()>tp) q.pop(),tp--;//如果剩下的时间不够等饭就t出去,因为max值已经记下,所以ta发挥的最大水平已经记录
scanf("%d",&x);x-=i;//还要等几分钟啊
if (x<=tp) q.push(x),dl++;//还来得及,那就等着试试
ans=max(dl,ans);
}
printf("%d",ans);
}
G题代码:
#include <cstdio>
#include <iostream>
using namespace std;
int cnt[10];char st[10];
int main()
{
int n,i,j;
scanf("%d",&n);
for (i=1;i<=n;i++)
{
scanf("%s",st);
for (j=0;j<7;j++)
if (st[j]=='1') cnt[j]++;
}
int ans=0;
for (i=0;i<7;i++) ans=max(ans,cnt[i]);
printf("%d",ans);
}
H题代码(莫队乱搞?注意1-n都有可能是最高哦):
#include <cstdio>
#include <iostream>
#define N 100005
#define LL long long
using namespace std;
int a[N],mq[N];
int main()
{
int n,i,r,l;
scanf("%d",&n);
if (n==1){printf("0");return 0;}
for (i=1;i<=n;i++) scanf("%d",&a[i]),mq[i]=a[i];
for (i=n;i>=1;i--)
mq[i]=max(mq[i+1]+1,a[i]);
mq[1]=max(mq[2]+1,max(mq[1],a[0]+1));
LL now=0,ans=0;
for (i=n;i>=1;i--)
now+=mq[i]-a[i]; ans=now;
for (i=2;i<=n;i++)
{
now-=mq[i-1];
mq[i-1]=max(mq[i-2]+1,a[i-1]);
now+=mq[i-1];
now-=mq[i];
mq[i]=max(max(mq[i+1]+1,a[i]),mq[i-1]+1);
now+=mq[i];
ans=min(ans,now);
}
printf("%lld",ans);
}
M题代码:
#include <cstdio>
using namespace std;
int n,i,a[105],ans;
int main()
{
bool fff=true;
scanf("%d",&n);scanf("%d",&a[1]);
for (i=2;i<=n;i++)
{
scanf("%d",&a[i]);
if (!ans) ans=a[i]-a[i-1];
else if (ans!=a[i]-a[i-1]) fff=false;
}
if (fff) printf("%d",a[n]+ans);
else printf("%d",a[n]);
}