18寒假12测

Day1


题目名称


party


array


treasure


输入


party.in


array.in


treasure.in


输出


party.out


array.out


treasure.out


每个测试点时限


1秒


1秒


1秒


内存限制


64MB


64MB


64MB


测试点数目


10


10


10


每个测试点分值


10


10


10


是否有部分分





题目类型


传统


传统


传统

party

题目描述:

在M公司里,每个人只有一个直属上司(除了boss)。这个公司举办派对,每个人可以给派对带来一定的欢乐值,但是每个人不能和自己的上司同时参加这个派对,求派对的最大欢乐值。

输入:

第一行n表示公司有n个人。

第二行n个数,表示每个人的上司是谁,如果这个人的上司为0,说明这个人是boss。

第三行n个数,表示每个人的欢乐值为wi。

输出:

一行一个数表示最大欢乐值。

样例输入:

6

0 1 1 1 4 4

1 1 1 1 1 1

样例输出:

4

解释:2 3 5 6 同时出席。

数据规模:

对于30%的数据,n<=20。

对于100%的数据,n<= 1000000,0<=w[i]<=1000。

题解:树形dp,dp[i][0/1]表示i号节点来不来,若父亲来,儿子肯定不来,若父亲不来,儿子随便来不来;

dp[i][0] = sum( max (dp[son[i]][0], dp[son[i]][1]); dp[i][1] = sum(dp[son[i]][0]);

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1000005;
int head[maxn],tot,dp[maxn][2];
struct edge{
    int to,nxt;
}G[maxn + 100];
void add(int u,int v){
    G[++tot].nxt = head[u];
    G[tot].to = v;
    head[u] = tot;
}
void dfs(int u, int f){

    for(int i = head[u]; i; i = G[i].nxt){
        int v = G[i].to;
        //if(v == f)continue;
        dfs(v, u);
        dp[u][1] += dp[v][0];
        dp[u][0] += max(dp[v][0], dp[v][1]);
    }
}
int main(){
    freopen("party.in","r",stdin);
    freopen("party.out","w",stdout);
    int n;
    scanf("%d",&n);
    for(int i = 1; i <= n; i++){
        int fa;
        scanf("%d",&fa);
        add(fa, i);
    }
    for(int i = 1; i <= n; i++){
        int w;
        scanf("%d",&w);
        dp[i][1] = w;
    }
    dfs(0, 0);
    cout<<dp[0][0]<<endl;
}

array

题目描述:

给定两个长度为n的排列p1和p2,求它们的最长公共子序列。

输入:

第一行一个数n。

接下来两个n个数分别表示p1和p2。

输出:

一个数表示最长子序列的长度。

样例输入:

3

1 2 3

2 1 3

样例输出:

2

解释及说明:

共有两种方案,分别为子序列为13和子序列为23.

数据规模:

对于30%的数据,n<=2000.

对于100%的数据,n<=100000。

题解:由于是排列,所以上下元素一样,且一个序列中无重复元素,我们就把一个序列的元素顺序做一个映射,在第二个序列中作最长上升子序列

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1000005;
int d[maxn], mp[maxn], q[maxn], tail;
int main(){
    freopen("array.in","r",stdin);
    freopen("array.out","w",stdout);
    int n, a, b;
    scanf("%d",&n);
    for(int i = 1; i <= n; i++){
        scanf("%d",&a);
        mp[a] = i;
    }
    for(int j = 1; j <= n; j++){
        scanf("%d",&b);
        d[j] = mp[b];
    }
    for(int i = 1; i <= n; i++){
        if(d[i] > q[tail])q[++tail] = d[i];
        else {
            int pos = lower_bound(q + 1, q + 1 + tail, d[i]) - q;
            q[pos] = d[i];
        }
    }
    cout<<tail<<endl;
}
 

treasure

题目描述:

小a可以攻打m座城堡,攻打每个城堡有不同的宝物,但是在攻打有些城堡前,需要攻打另外的城堡。小a想知道,能获得的最多宝物是多少?

输入:

第一行两个数,n,m。分别表示有n个城堡,可以攻打m个。

接下来n行每行两个数a,b,分别表示在攻打第i个城堡前需要攻打a,攻打后获得b的宝物。

输出:

一行一个数ans表示可以获得的最大宝物数量。

样例输入

3 2

0 1

0 2

0 3

7 4

2 2

0 1

0 4

2 1

7 1

7 6

2 2

0 0

样例输出:

5

13

数据规模:

对于30%的数据,n<=20,m<=20。

对于100%的数据,n<=500,m<=500,b[i]<=1000。

题解:树形DP,这道题很像树上染色,但不用考虑子树和外界 联系,要简单一点;

dp[i][j]表示给i为根的子树分配j次攻打机会可获得最大的利益,答案就为dp[root][m];

由于必须打父亲,才能打儿子,所以儿子可分配的机会为j-1,但0号点是我们假设的城堡,故他的子树有j次机会,特判一下,然后做一个分组背包就好了,因为一个子树分配的机会只能有一种方案;

抽象一下:每个子树为一组,可供选择的物品为min(siz[father], j), 容量为min(siz[son],j);

#include<bits/stdc++.h>
using namespace std;

const int maxn = 505;
int n,m;
int head[maxn],tot,dp[maxn][maxn],siz[maxn];
struct edge{
    int to,nxt,w;
}G[maxn + 100];
void add(int u,int v,int w){
    G[++tot].nxt = head[u];
    G[tot].to = v;
    G[tot].w = w;
    head[u] = tot;
}
void dfs(int u){
    for(int i = head[u]; i; i = G[i].nxt){
        int v = G[i].to;
        dfs(v);
        int V = min(siz[u], m);
        int K = min(siz[v], m);
        for(int s = V; s >= 1; s--)
            for(int j = 1; j <= ( u == 0 ? min(s, K) : min(s-1, K) ); j++){
                dp[u][s] = max( dp[u][s], dp[u][s - j] + dp[v][j] + G[i].w);
            }

    }
}
void get_size(int u){
    siz[u] = 1;
    for(int i = head[u]; i; i = G[i].nxt){
        int v = G[i].to;
        get_size(v);
        siz[u] += siz[v];
    }
}

int main(){
    freopen("treasure.in","r",stdin);
    freopen("treasure.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i = 1; i <= n; i++){
        int fa,w;
        scanf("%d%d",&fa,&w);
        add(fa, i, w);
    }
    get_size(0);
    dfs(0);
    cout<<dp[0][m]<<endl;
}

考试突然不会分组背包了,╮(╯▽╰)╭, 一定要记得容量放外面,从大到小啊

原文地址:https://www.cnblogs.com/EdSheeran/p/8502658.html

时间: 2024-11-09 02:47:30

18寒假12测的相关文章

18寒假第一测

猪猪的想法输入文件:thought.in输出文件:thought.out时间限制:1 second空间限制:128 MB题目描述狗蛋养了许多只可爱的猪猪,这些猪猪她萌都有一些奇怪的想法:比如说猪猪喜欢猪猪,猪猪之间的喜欢是一个很有趣的事情--喜欢是可以传递的,例如猪猪喜欢猪猪,猪猪喜欢猪猪,那么可以说猪猪喜欢猪猪.有意思的一点是,她萌不喜欢自恋的猪猪,一旦出现了自恋的猪猪,那么极有可能的是这个团体出现危险.现在给你只猪猪对单方面的关系,请问这个只猪猪组成的团体是否危险呢?是输出Yes ,否输出N

18寒假第二测

第一题:二维树状数组,bit[x][y]表示从(1,1)到(x,y)的和,二维的坐标从一维的推过来,正确性可以用一个递增和一个递减的序列单调性证明,至于构图就当黑箱吧 #include <cstdio> int n, m, q; struct Case1 { int bit[100010]; void modify( int p, int d ) { for( int i = p; i <= m; i += i & -i ) bit[i] += d; } int query( i

18寒假13测

题目名称 buy slide divide 输入 buy.in slide.in divide.in 输出 buy.out slide.out divide.out 每个测试点时限 1秒 1秒 1秒 内存限制 256MB 256MB 256MB 测试点数目 10 10 10 每个测试点分值 10 10 10 是否有部分分 无 无 无 题目类型 传统 传统 传统 buy description: 地主zxr想买一些长方形的土地,所有的土地可以分为若干组,每一组的土地的价格为这一组里的最长的长乘上最

18寒假第三测

第一题:找LCA,两点之间的距离=他们各自到起点的距离 - 2*LCA到起点的距离 #include<bits/stdc++.h> using namespace std; const int maxn = 100015, P = 20; int head[2 * maxn],to[2 * maxn],last[2 *maxn],co[2 * maxn],dep[maxn], idx, anc[maxn][P+1],dis[maxn]; void dfs(int u,int from){ //

18寒假第六测

第一题:乘法修改的线段树 一定不能将change,modify分类讨论定两个标记,会有顺序影响 lazy标记一定要long long,又忘了... 代码和上一次差不多 第二题:离散暴力,也可以扫描线 离散时要将格子映射成点,不然会出现以下情况: 算横着的小矩形宽就是2,算黄色面积宽还是2,因为没有2让3去减 如果映射成点,就像这样,,放图比较好理解,就像扫描线,一个叶子节点存的是一个左闭右开的区间 也可以离散+扫描线,但还没写出来 #include <bits/stdc++.h> using

18寒假第五测

第一题 线段树 树状数组存差b[i] = a[i]-a[i-1],反正是单点查询,我为什么没想到...很傻的用线段树 #include<bits/stdc++.h> using namespace std; #define maxn 100005 #define ll long long int n, m, a[maxn]; struct SegmentTree{ struct node{ ll sum; int lazy; }; node Tree[maxn << 2]; #de

18.03.12 vijos1037搭建双塔

描述 2001年9月11日,一场突发的灾难将纽约世界贸易中心大厦夷为平地,Mr. F曾亲眼目睹了这次灾难.为了纪念“9?11”事件,Mr. F决定自己用水晶来搭建一座双塔. Mr. F有N块水晶,每块水晶有一个高度,他想用这N块水晶搭建两座有同样高度的塔,使他们成为一座双塔,Mr. F可以从这N块水晶中任取M(1≤M≤N)块来搭建.但是他不知道能否使两座塔有同样的高度,也不知道如果能搭建成一座双塔,这座双塔的最大高度是多少.所以他来请你帮忙. 给定水晶的数量N(1≤N≤100)和每块水晶的高度H

18.5.12 c++选做题#4

4:自己实现bitset 描述程序 填空,实现一个类似STL bitset的 MyBitset, 输出指定结果 #include <iostream> #include <cstring> using namespace std; template <int bitNum> struct MyBitset { char a[bitNum/8+1]; MyBitset() { memset(a,0,sizeof(a));}; void Set(int i,int v) {

2020寒假 12

发现一个问题: bs4 FeatureNotFound: Couldn't find a tree builder with the features you requested: lxml. Do you need to install a parser library? 解决方法:将"lxml"改成"html.parser" soup = BeautifulSoup(content, "lxml")改成 soup = BeautifulSou