20180717练习赛 [CF]498DIV3
A - Polycarp’s Practice CodeForces - 1006B
B - Three Parts of the Array CodeForces - 1006C
C - Two Strings Swaps CodeForces - 1006D
D - Military Problem CodeForces - 1006E
A
给你k天时间解决n个问题,每个问题都有一个价值。所有问题必须按顺序解决且在第k天完成。定义每天的价值为当天解决的问题的最大价值,求k天最大的总价值。
说白了就是要把n个数划分成k段,每段的值为那一段数的最大的哪一个,求每段总和的最大值
要使价值最大,我们应将前k大的数全部分在不同的段里面。而无论顺序如何,这是肯定可以做到的(不明白就打一下草稿,捯饬捯饬)
所以答案好求,但是这题要输出方案。
所以排序的时候带个结构体,算了前k大,再排回来。(而实际上只需要排前k大就可以了)
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 2005
int N,K,ans,cn;
struct node{
int v,p;
}a[MAXN],c[MAXN];
int b[MAXN];
bool cmp(node x,node y)
{
return x.v>y.v;
}
bool cmp2(node x,node y)
{
return x.p<y.p;
}
int main()
{
scanf("%d %d",&N,&K);
for(int i=1;i<=N;i++)
{
scanf("%d",&a[i].v);
a[i].p=i;
b[i]=a[i].v;
}
sort(a+1,a+N+1,cmp);
for(int i=1;i<=K;i++)
{
ans+=a[i].v;
c[++cn].v=a[i].v;
c[cn].p=a[i].p;
}
sort(c+1,c+cn+1,cmp2);
int n=1;
printf("%d\n",ans);
int last=0;
for(int i=1;i<=N;i++)
if(b[i]==c[n].v)
{
if(n==cn)
{
printf("%d",N-last);
return 0;
}
printf("%d ",i-last);
last=i;
n++;
}
}
其实我的实现好像有点绕,b数组有点多余,给a排一下序就可以达到目的
B
一个长度为n的数组,按顺序分成三部分,要求第一部分和第三部分元素的和相等(每一部分都可以没有元素,没有元素的部分元素和为0),求出第一部分和第三部分最大的相等的元素和,如果没有输出0
记录了一个前缀和和后缀和,找相等的最大值,由于分成2个数组直接枚举判断会超时,我用了一个结构体排序,标记了它们的类别(前缀or后缀),由于不能有重合部分,还标记了它们的位置。
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 200005
int N,ans;
int a[MAXN];
struct node{
long long v;
int p,t;
}b[2*MAXN];
bool cmp(node x,node y)
{
return x.v>y.v;
}
int main()
{
scanf("%d",&N);
for(int i=1;i<=N;i++)
{
scanf("%d",&a[i]);
b[i].v=b[i-1].v+a[i];
b[i].p=i;
b[i].t=1;
}
for(int i=N;i>=1;i--)
b[i+N].v=b[i+N+1].v+a[i],b[i+N].p=i,b[i+N].t=2;
sort(b+1,b+2*N+2,cmp);
for(int i=1;i<=2*N;i++)
if(b[i].v==b[i+1].v&&((b[i].p<b[i+1].p&&b[i].t==1&&b[i+1].t==2)||(b[i].p>b[i+1].p&&b[i].t==2&&b[i+1].t==1)))
{
printf("%lld\n",b[i].v);
return 0;
}
printf("0\n");
return 0;
}
//long long不开毁前程
C
这道题我被坑了很久
之前单独写过一篇博客
后来不知道csdn出了什么玄幻的BUG
博客被吞了qwq
o(╥﹏╥)o
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 100005
char a[MAXN],b[MAXN];
int N,ans;
int main()
{
scanf("%d",&N);
scanf("%s\n%s",a+1,b+1);
for(int i=1;i<=N;i++)
if(a[i]!=b[i])
{
int j=N-i+1;
if(j>i)
{
if(a[i]==b[j]) swap(b[i],b[j]);
else if(b[i]==a[j]) swap(a[i],a[j]);
//else if(a[i]==a[j]) swap(a[i],b[i]),swap(a[i],a[j]);
else if(a[j]==b[j]) swap(a[i],a[j]),swap(b[i],b[j]);
else if(b[i]==b[j]) swap(a[i],b[i]),swap(b[i],b[j]);
else ans++;
}
else ans++;
}
printf("%d\n",ans);
}
D
给你一个有根树,根为1,大小为n,进行q次询问。每次询问要求出以u为根的子树中,dfs序第k个的节点,若不存在则输-1
就是一个dfs序的问题
#include<cstdio>
#include<vector>
using namespace std;
#define MAXN 200005
int n,q,dcnt;
int dfn[MAXN],num[MAXN],mx[MAXN];
vector<int> G[MAXN];
void dfs(int u)
{
dfn[u]=++dcnt;
num[dcnt]=u;
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(!dfn[v])
dfs(v);
}
mx[u]=dcnt;
}
int main()
{
scanf("%d %d",&n,&q);
for(int i=2;i<=n;i++)
{
int u;
scanf("%d",&u);
G[u].push_back(i);
G[i].push_back(u);
}
dfs(1);
while(q--)
{
int u,k;
scanf("%d %d",&u,&k);
int tmp=dfn[u]+k-1;
if(mx[u]<tmp)
{
printf("-1\n");
continue;
}
printf("%d\n",num[tmp]);
}
}