把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

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]);
    }
}
posted @ 2018-08-24 09:19  Starlight_Glimmer  阅读(4)  评论(0编辑  收藏  举报  来源
浏览器标题切换
浏览器标题切换end