NOIP2025题解
P14635 [NOIP2025] 糖果店 / candy(官方数据)
P14635 [NOIP2025] 糖果店 / candy(官方数据)
题目描述
小 X 开了一家糖果店,售卖 nnn 种糖果,每种糖果均有无限颗。对于不同种类的糖果,小 X 采用了不同的促销策略。具体地,对于第 iii (1≤i≤n1 \le i \le n1≤i≤n) 种糖果,购买第一颗的价格为 xix_ixi 元,第二颗为 yiy_iyi 元,第三颗又变回 xix_ixi 元,第四颗则为 yiy_iyi 元,以此类推。
小 R 带了 mmm 元钱买糖果。小 R 不关心糖果的种类,只想得到数量尽可能多的糖果。你需要帮助小 R 求出,mmm 元钱能购买的糖果数量的最大值。
输入格式
输入的第一行包含两个正整数 n,mn, mn,m,代表糖果的种类数和小 R 的钱数。
输入的第 i+1i+1i+1 (1≤i≤n1 \le i \le n1≤i≤n) 行包含两个正整数 xi,yix_i, y_ixi,yi,分别表示购买第 iii 种糖果时第奇数颗的价格和第偶数颗的价格。
输出格式
输出一行一个非负整数,表示 mmm 元钱能购买的糖果数量的最大值。
输入输出样例 #1
输入 #1
2 10
4 1
3 3
输出 #1
4
输入输出样例 #2
输入 #2
3 15
1 7
2 3
3 1
输出 #2
8
说明/提示
【样例 1 解释】
小 R 可以购买 4 颗第一种糖果,共花费 4+1+4+1=104 + 1 + 4 + 1 = 104+1+4+1=10 元。
【样例 2 解释】
小 R 可以购买 1 颗第一种糖果、1 颗第二种糖果与 6 颗第三种糖果,共花费 1+2+12=151 + 2 + 12 = 151+2+12=15 元。
【样例 3】
见选手目录下的 candy/candy3.in 与 candy/candy3.ans。
该样例满足测试点 666 的约束条件。
【样例 4】
见选手目录下的 candy/candy4.in 与 candy/candy4.ans。
该样例满足测试点 8,98,98,9 的约束条件。
【样例 5】
见选手目录下的 candy/candy5.in 与 candy/candy5.ans。
该样例满足测试点 11,1211,1211,12 的约束条件。
【样例 6】
见选手目录下的 candy/candy6.in 与 candy/candy6.ans。
该样例满足测试点 131313 的约束条件。
【样例 7】
见选手目录下的 candy/candy7.in 与 candy/candy7.ans。
该样例满足测试点 17,1817,1817,18 的约束条件。
【数据范围】
对于所有测试数据,均有:
- 1≤n≤1051 \le n \le 10^51≤n≤105;
- 1≤m≤10181 \le m \le 10^{18}1≤m≤1018;
- 对于所有 1≤i≤n1 \le i \le n1≤i≤n,均有 1≤xi,yi≤1091 \le x_i, y_i \le 10^91≤xi,yi≤109。
::cute-table{tuack}
| 测试点编号 | n≤n \len≤ | m≤m \lem≤ | 特殊性质 |
|---|---|---|---|
| 111 | 111 | 101010 | 无 |
| 2,32,32,3 | 222 | 202020 | ^ |
| 4,54,54,5 | 101010 | ^ | ^ |
| 666 | 10210^2102 | 10210^2102 | A |
| 777 | ^ | ^ | B |
| 8,98,98,9 | ^ | ^ | 无 |
| 101010 | 10310^3103 | 10410^4104 | A |
| 11,1211,1211,12 | ^ | ^ | B |
| 131313 | ^ | ^ | 无 |
| 141414 | 10510^5105 | 10910^9109 | A |
| 15,1615,1615,16 | ^ | ^ | B |
| 17,1817,1817,18 | ^ | ^ | 无 |
| 19,2019,2019,20 | ^ | 101810^{18}1018 | ^ |
特殊性质 A:对于所有 1≤i≤n1 \le i \le n1≤i≤n,均有 xi=yix_i = y_ixi=yi。
特殊性质 B:对于所有 1≤i≤n1 \le i \le n1≤i≤n,均有 xi≥yix_i \ge y_ixi≥yi。
思路
从小到大枚举x是否选,再看x+y最大选几个,贪心即可。
代码见下
#include<bits/stdc++.h>
using namespace std;
long long n,m,mi=1e18+7,op=0;
struct one{
long long x,y;
}a[100005];
bool cmp(one a1,one b1){
return a1.x<b1.x;
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i].x>>a[i].y;
mi=min(mi,a[i].x+a[i].y);
}
sort(a+1,a+n+1,cmp);
op=((m/mi)*2);
for(int i=1;i<=n;i++){
m-=a[i].x;
if(m<=0){
break;
}
op=max(op,(m/mi)*2+i);
}
cout<<op<<endl;
return 0;
}
P14636 [NOIP2025] 清仓甩卖 / sale(官方数据)
P14636 [NOIP2025] 清仓甩卖 / sale(官方数据)
题目描述
小 X 的糖果促销策略很成功,现在糖果店只剩下了 nnn 颗糖果,其中第 iii (1≤i≤n1 \le i \le n1≤i≤n) 颗糖果的原价为 aia_iai 元。小 X 计划将它们全部重新定价,清仓甩卖。具体地,小 X 会将每颗糖果的清仓价格分别定为 1 元或 2 元。设第 iii (1≤i≤n1 \le i \le n1≤i≤n) 颗糖果的清仓价格为 wi∈{1,2}w_i \in \{1,2\}wi∈{1,2} 元,则它的性价比被定义为原价与清仓价格的比值,即 aiwi\frac{a_i}{w_i}wiai。
小 R 又带了 mmm 元钱买糖果。这一次,小 R 希望他购买到的糖果的原价总和最大,于是他采用了以下购买策略:将所有糖果按照性价比从大到小排序,然后依次考虑每一颗糖果。具体地,若小 R 在考虑第 iii (1≤i≤n1 \le i \le n1≤i≤n) 颗糖果时剩余的钱至少为 wiw_iwi 元,则他会购买这颗糖果;否则他会跳过这颗糖果,继续考虑下一颗。特别地,若存在两颗糖果的性价比相同,则小 R 会先考虑原价较高的糖果;若存在两颗糖果的性价比与原价均相同,则小 R 会先考虑编号较小的糖果。
例如,若小 X 的糖果商店剩余 3 颗糖果,原价分别为 a1=1a_1=1a1=1,a2=3a_2=3a2=3,a3=5a_3=5a3=5,而清仓价格分别为 w1=w2=1w_1=w_2=1w1=w2=1,w3=2w_3=2w3=2,则性价比分别为 1,3,521, 3, \frac{5}{2}1,3,25。因此小 R 会先考虑第 2 颗糖果,然后考虑第 3 颗糖果,最后考虑第 1 颗糖果。
小 R 想知道,在小 X 的所有 2n2^n2n 种定价方案中,有多少种定价方案使得他按照上述购买策略能购买到的糖果的原价总和最大。你需要帮助小 R 求出满足要求的定价方案的数量。由于答案可能较大,你只需要求出答案对 998,244,353998,244,353998,244,353 取模后的结果。
输入格式
本题包含多组测试数据。
输入的第一行包含两个非负整数 c,tc, tc,t,分别表示测试点编号与测试数据组数。c=0c=0c=0 表示该测试点为样例。
接下来依次输入每组测试数据,对于每组测试数据:
- 第一行包含两个正整数 n,mn, mn,m,分别表示糖果的数量与小 R 的钱数;
- 第二行包含 nnn 个正整数 a1,a2,…,ana_1, a_2, \ldots, a_na1,a2,…,an,分别表示每颗糖果的原价。
输出格式
对于每组测试数据,输出一行一个非负整数,表示使得小 R 购买到的糖果的原价总和达到最大值的定价方案数对 998,244,353998,244,353998,244,353 取模后的结果。
输入输出样例 #1
输入 #1
0 1
3 2
1 3 5
输出 #1
6
说明/提示
【样例 1 解释】
该样例即为【题目描述】中的例子。共有以下 6 种定价方案使得小 R 购买到的糖果原价总和最大,分别为:
- w1=w2=w3=1w_1 = w_2 = w_3 = 1w1=w2=w3=1,小 R 购买到的糖果原价总和为 8;
- w1=w3=1w_1 = w_3 = 1w1=w3=1,w2=2w_2 = 2w2=2,小 R 购买到的糖果原价总和为 6;
- w1=1w_1 = 1w1=1,w2=w3=2w_2 = w_3 = 2w2=w3=2,小 R 购买到的糖果原价总和为 5;
- w2=w3=1w_2 = w_3 = 1w2=w3=1,w1=2w_1 = 2w1=2,小 R 购买到的糖果原价总和为 8;
- w3=1w_3 = 1w3=1,w1=w2=2w_1 = w_2 = 2w1=w2=2,小 R 购买到的糖果原价总和为 5;
- w1=w2=w3=2w_1 = w_2 = w_3 = 2w1=w2=w3=2,小 R 购买到的糖果原价总和为 5。
注意:若 w1=w2=1w_1 = w_2 = 1w1=w2=1,w3=2w_3 = 2w3=2,则小 R 会依次购买第 2 颗和第 1 颗糖果,原价总和为 4,但小 R 可以只购买第 3 颗糖果,原价总和为 5。因此该定价方案无法使小 R 购买到的糖果的原价总和达到最大值。
【样例 2】
见选手目录下的 sale/sale2.in 与 sale/sale2.ans。
该样例满足测试点 1∼31 \sim 31∼3 的约束条件。
【样例 3】
见选手目录下的 sale/sale3.in 与 sale/sale3.ans。
该样例满足测试点 4,54,54,5 的约束条件。
【样例 4】
见选手目录下的 sale/sale4.in 与 sale/sale4.ans。
该样例满足测试点 7∼97 \sim 97∼9 的约束条件。
【样例 5】
见选手目录下的 sale/sale5.in 与 sale/sale5.ans。
该样例满足测试点 10∼1210 \sim 1210∼12 的约束条件。
【样例 6】
见选手目录下的 sale/sale6.in 与 sale/sale6.ans。
该样例满足测试点 131313 的约束条件。
【样例 7】
见选手目录下的 sale/sale7.in 与 sale/sale7.ans。
该样例满足测试点 14,1514,1514,15 的约束条件。
【样例 8】
见选手目录下的 sale/sale8.in 与 sale/sale8.ans。
该样例满足测试点 171717 的约束条件。
【样例 9】
见选手目录下的 sale/sale9.in 与 sale/sale9.ans。
该样例满足测试点 19,2019,2019,20 的约束条件。
【样例 10】
见选手目录下的 sale/sale10.in 与 sale/sale10.ans。
该样例满足测试点 21∼2321 \sim 2321∼23 的约束条件。
【样例 11】
见选手目录下的 sale/sale11.in 与 sale/sale11.ans。
该样例满足测试点 24,2524,2524,25 的约束条件。
【数据范围】
设 NNN 为单个测试点内所有测试数据的 nnn 的和。对于所有测试数据,均有:
- 1≤t≤5×1041 \le t \le 5 \times 10^41≤t≤5×104;
- 1≤n≤5,0001 \le n \le 5,0001≤n≤5,000,N≤5×104N \le 5 \times 10^4N≤5×104,1≤m≤2n−11 \le m \le 2n - 11≤m≤2n−1;
- 对于所有 1≤i≤n1 \le i \le n1≤i≤n,均有 1≤ai≤1091 \le a_i \le 10^91≤ai≤109。
::cute-table{tuack}
| 测试点编号 | n≤n \len≤ | N≤N \leN≤ | mmm | 特殊性质 |
|---|---|---|---|---|
| 1∼31\sim 31∼3 | 555 | 5,0005{,}0005,000 | ≤2n−1\le 2n - 1≤2n−1 | 无 |
| 4,54,54,5 | 101010 | ^ | ^ | ^ |
| 666 | 404040 | ^ | ^ | ^ |
| 7∼97\sim 97∼9 | 300300300 | ^ | =2=2=2 | ^ |
| 10∼1210\sim 1210∼12 | ^ | ^ | ≤2n−1\le 2n - 1≤2n−1 | B |
| 131313 | ^ | ^ | ^ | 无 |
| 14,1514,1514,15 | 10310^3103 | 10410^4104 | =2=2=2 | ^ |
| 161616 | ^ | ^ | =2n−1=2n - 1=2n−1 | ^ |
| 171717 | ^ | ^ | =2n−2=2n - 2=2n−2 | ^ |
| 181818 | ^ | ^ | ≤2n−1\le 2n - 1≤2n−1 | A |
| 19,2019,2019,20 | ^ | ^ | ^ | B |
| 21∼2321\sim 2321∼23 | ^ | ^ | ^ | 无 |
| 24,2524,2524,25 | 5,0005{,}0005,000 | 5×1045 \times 10^45×104 | ^ | ^ |
特殊性质 A:a1=a2=⋯=ana_1 = a_2 = \cdots = a_na1=a2=⋯=an。
特殊性质 B:对于所有 1≤i≤n1 \le i \le n1≤i≤n,均有 ai>5×108a_i > 5 \times 10^8ai>5×108。
思路
1+2形式,枚举1,2即可。
代码见下
#include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
int c,t,n,m,a[10005],p2[10005],f[10005][10005],op=0;
int main(){
//freopen("sale.in","r",stdin);
//freopen("sale.out","w",stdout);
cin>>c>>t;
f[0][0]=1;
for(int i=1;i<=5000;i++){
f[i][0]=1;
for(int j=1;j<=5000;j++){
f[i][j]=(f[i-1][j]+f[i-1][j-1])%mod;
}
}
p2[0]=1;
for(int i=1;i<=5000;i++){
p2[i]=p2[i-1]*2%mod;
}
while(t--){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
}
sort(a+1,a+n+1);
op=p2[n];
for(int i=1,p=0;i<=n;i++){
p=0;
for(int j=i+1;j<=n;j++){
if(a[j]>=a[i]*2){
break;
}
if(a[i]!=a[j]){
while(p<=n-1&&a[p+1]+a[i]<=a[j]-1){
p++;
}
op=(op-(long long)f[n-i-1][m-2-(n-j)]*p2[p]%mod+mod)%mod;
}
}
}
cout<<op<<endl;
}
return 0;
}
P14638 [NOIP2025] 序列询问 / query(官方数据)
P14638 [NOIP2025] 序列询问 / query(官方数据)
题目描述
给定一个长度为 nnn 的整数序列 a1,a2,…,ana_1, a_2, \ldots, a_na1,a2,…,an。
有 qqq 次询问,其中第 jjj (1≤j≤q1 \le j \le q1≤j≤q) 次询问将会给出 Lj,RjL_j, R_jLj,Rj (1≤Lj≤Rj≤n1 \le L_j \le R_j \le n1≤Lj≤Rj≤n)。定义区间 [l,r][l, r][l,r] (1≤l≤r≤n1 \le l \le r \le n1≤l≤r≤n) 是极好的,当且仅当区间 [l,r][l, r][l,r] 的长度在 [Lj,Rj][L_j, R_j][Lj,Rj] 内,即 Lj≤r−l+1≤RjL_j \le r - l + 1 \le R_jLj≤r−l+1≤Rj。定义区间 [l,r][l, r][l,r] (1≤l≤r≤n1 \le l \le r \le n1≤l≤r≤n) 的权值为 ∑i=lrai\sum_{i=l}^{r} a_i∑i=lrai。对于所有 i=1,2,…,ni = 1, 2, \ldots, ni=1,2,…,n,求出所有包含 iii 的极好区间的最大权值,即 max1≤l≤i≤r≤n{∑i=lrai∣Lj≤r−l+1≤Rj}\max_{1 \le l \le i \le r \le n} \{ \sum_{i=l}^{r} a_i \mid L_j \le r - l + 1 \le R_j \}max1≤l≤i≤r≤n{∑i=lrai∣Lj≤r−l+1≤Rj}。
输入格式
输入的第一行包含一个正整数 nnn,表示序列长度。
输入的第二行包含 nnn 个整数 a1,a2,…,ana_1, a_2, \ldots, a_na1,a2,…,an。
输入的第三行包含一个正整数 qqq,表示询问次数。
输入的第 j+3j + 3j+3 (1≤j≤q1 \le j \le q1≤j≤q) 行包含两个正整数 Lj,RjL_j, R_jLj,Rj,表示第 jjj 次询问。
输出格式
对于每次询问,设包含 iii (1≤i≤n1 \le i \le n1≤i≤n) 的极好区间的最大权值为 kik_iki,输出一行一个非负整数,表示 ⨁i=1n((i×ki) mod 264)\bigoplus_{i=1}^{n} \left( (i \times k_i) \bmod 2^{64} \right)⨁i=1n((i×ki)mod264),其中 ⊕\oplus⊕ 表示二进制按位异或。注意:对于任意整数 xxx,存在唯一的非负整数 x′x'x′ 满足 x′≡x(mod264)x' \equiv x \pmod{2^{64}}x′≡x(mod264) 且 0≤x′≤264−10 \le x' \le 2^{64} - 10≤x′≤264−1,则记 x mod 264=x′x \bmod 2^{64} = x'xmod264=x′。
输入输出样例 #1
输入 #1
4
2 4 -5 1
3
1 2
3 4
1 4
输出 #1
18446744073709551603
8
4
说明/提示
【样例 1 解释】
对于第 111 次询问:
- 包含 111 的极好区间为 [1,1][1,1][1,1] 和 [1,2][1,2][1,2],权值分别为 2,62,62,6;
- 包含 222 的极好区间为 [1,2][1,2][1,2],[2,2][2,2][2,2] 和 [2,3][2,3][2,3],权值分别为 6,4,−16,4,-16,4,−1;
- 包含 333 的极好区间为 [2,3][2,3][2,3],[3,3][3,3][3,3] 和 [3,4][3,4][3,4],权值分别为 −1,−5,−4-1,-5,-4−1,−5,−4;
- 包含 444 的极好区间为 [3,4][3,4][3,4] 和 [4,4][4,4][4,4],权值分别为 −4,1-4,1−4,1。
因此 k1=6k_1 = 6k1=6,k2=6k_2 = 6k2=6,k3=−1k_3 = -1k3=−1,k4=1k_4 = 1k4=1。
对于第 2 次询问,k1=2k_1 = 2k1=2,k2=2k_2 = 2k2=2,k3=2k_3 = 2k3=2,k4=2k_4 = 2k4=2。
对于第 3 次询问,k1=6k_1 = 6k1=6,k2=6k_2 = 6k2=6,k3=2k_3 = 2k3=2,k4=2k_4 = 2k4=2。
【样例 2】
见选手目录下的 query/query2.in 与 query/query2.ans。
该样例满足测试点 2,32,32,3 的约束条件。
【样例 3】
见选手目录下的 query/query3.in 与 query/query3.ans。
该样例满足测试点 444 的约束条件。
【样例 4】
见选手目录下的 query/query4.in 与 query/query4.ans。
该样例满足测试点 6,76,76,7 的约束条件。
【样例 5】
见选手目录下的 query/query5.in 与 query/query5.ans。
该样例满足测试点 8∼108 \sim 108∼10 的约束条件。
【样例 6】
见选手目录下的 query/query6.in 与 query/query6.ans。
该样例满足测试点 11,1211,1211,12 的约束条件。
【样例 7】
见选手目录下的 query/query7.in 与 query/query7.ans。
该样例满足测试点 131313 的约束条件。
【样例 8】
见选手目录下的 query/query8.in 与 query/query8.ans。
该样例满足测试点 16∼2016 \sim 2016∼20 的约束条件。
【数据范围】
对于所有测试数据,均有:
- 1≤n≤5×1041 \le n \le 5 \times 10^41≤n≤5×104,1≤q≤1,0241 \le q \le 1,0241≤q≤1,024;
- 对于所有 1≤i≤n1 \le i \le n1≤i≤n,均有 ∣ai∣≤105|a_i| \le 10^5∣ai∣≤105;
- 对于所有 1≤j≤q1 \le j \le q1≤j≤q,均有 1≤Lj≤Rj≤n1 \le L_j \le R_j \le n1≤Lj≤Rj≤n。
::cute-table{tuack}
| 测试点编号 | n≤n \len≤ | q≤q \leq≤ | 特殊性质 |
|---|---|---|---|
| 111 | 10310^3103 | 111 | 无 |
| 2,32,32,3 | 3,0003{,}0003,000 | 505050 | ^ |
| 444 | 10410^4104 | 128128128 | ^ |
| 555 | 3×1043 \times 10^43×104 | 512512512 | ^ |
| 6,76,76,7 | 5×1045 \times 10^45×104 | 1,0241{,}0241,024 | A |
| 8∼108 \sim 108∼10 | ^ | 512512512 | B |
| 11,1211,1211,12 | ^ | ^ | C |
| 131313 | ^ | 1,0241{,}0241,024 | D |
| 14,1514,1514,15 | ^ | ^ | E |
| 16∼2016 \sim 2016∼20 | ^ | ^ | 无 |
特殊性质 A:对于所有 1≤j≤q1 \le j \le q1≤j≤q,均有 Lj=RjL_j = R_jLj=Rj。
特殊性质 B:对于所有 1≤j≤q1 \le j \le q1≤j≤q,均有 Rj≤32R_j \le 32Rj≤32。
特殊性质 C:对于所有 1≤j≤q1 \le j \le q1≤j≤q,均有 Lj≤16L_j \le 16Lj≤16 且 Rj≥n−1000R_j \ge n - 1000Rj≥n−1000。
特殊性质 D:对于所有 1≤j≤q1 \le j \le q1≤j≤q,均有 Lj>n/2L_j > n/2Lj>n/2。
特殊性质 E:对于所有 1≤j≤q1 \le j \le q1≤j≤q,均有 Lj>n/4L_j > n/4Lj>n/4。
代码
#include<bits/stdc++.h>
using namespace std;
long long n,a[50004],l,r,k,ll,rr,st[50004],ma[50004],mi[50004],b[50004],w[50004],q;
unsigned long long op=0;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
a[i]+=a[i-1];
}
cin>>q;
for(int qwepoi=1;qwepoi<=q;qwepoi++){
cin>>l>>r;
k=(r-l)/2;
ll=1;
rr=0;
for(int i=n;~i;i--){
while(ll<=rr&&st[ll]>=i+k+1){
ll++;
}
while(ll<=rr&&a[st[rr]]<=a[i]){
rr--;
}
st[++rr]=i;
ma[i]=a[st[ll]];
}
ll=1;
rr=0;
for(int i=0;i<=n;i++){
while(ll<=rr&&st[ll]<=i-k-1){
ll++;
}
while(ll<=rr&&a[st[rr]]>=a[i]){
rr--;
}
st[++rr]=i;
mi[i]=a[st[ll]];
}
for(int i=1;i<=l-1;i++){
b[i]=-1e18-7;
}
for(int i=l;i<=n;i++){
b[i]=ma[i]-mi[i-l];
}
for(int i=1;i<=n-r+k+1;i++){
w[i]=max(ma[i+l-1],ma[i+r-k-1])-a[i-1];
}
for(int i=n-r+k+2;i<=n-l+1;i++){
w[i]=ma[i+l-1]-a[i-1];
}
for(int i=n-l+2;i<=n;i++){
w[i]=-1e18-7;
}
ll=1;
rr=0;
for(int i=1;i<=n;i++){
while(ll<=rr&&st[ll]<=i-l){
ll++;
}
while(ll<=rr&&w[st[rr]]<=w[i]){
rr--;
}
st[++rr]=i;
b[i]=max(b[i],w[st[ll]]);
}
if(r-l==2*k){
for(int i=l;i<=n-k;i++){
w[i]=max(ma[i+k]-a[i-l],a[i+k]-mi[i-l]);
}
}
else{
for(int i=l;i<=n-k;i++){
w[i]=max(max(ma[i+k],a[min(n,i+r-l)])-a[i-l],a[i+k]-min(mi[i-l],a[max(0ll,i-r+k)]));
}
}
for(int i=n-k+1;i<=n;i++){
w[i]=-1e18-7;
}
ll=1;
rr=0;
for(int i=l;i<=n;i++){
while(ll<=rr&&st[ll]<=i-k-1){
ll++;
}
while(ll<=rr&&w[st[rr]]<=w[i]){
rr--;
}
st[++rr]=i;
b[i]=max(b[i],w[st[ll]]);
}
op=0;
for(int i=1;i<=n;i++){
op=op^((unsigned long long)(b[i]*i));
}
cout<<op<<endl;
}
return 0;
}
P14637 [NOIP2025] 树的价值 / tree(官方数据)
P14637 [NOIP2025] 树的价值 / tree(官方数据)
题目描述
给定一棵 nnn 个结点的有根树,其中结点 1 为根,结点 iii (2≤i≤n2 \le i \le n2≤i≤n) 的父亲结点为结点 pip_ipi。
对于 1≤i≤n1 \le i \le n1≤i≤n,定义结点 iii 的深度 did_idi 为结点 1 到结点 iii 的简单路径的边数,也就是说,d1=0d_1 = 0d1=0,di=dpi+1d_i = d_{p_i} + 1di=dpi+1 (2≤i≤n2 \le i \le n2≤i≤n)。定义有根树的高度 hhh 为所有结点的深度的最大值,即 h=maxi=1ndih = \max_{i=1}^{n} d_ih=maxi=1ndi。
给定高度的上界 mmm。在本题中,给定的有根树的高度不超过 mmm。
你需要给每个结点设置一个非负整数作为它的权值。对于 1≤i≤n1 \le i \le n1≤i≤n,若结点 iii 的权值为 aia_iai,令 SiS_iSi 表示结点 iii 的子树中结点权值构成的集合。对于每一种权值设置方案,定义树的价值为 ∑i=1nmex(Si)\sum_{i=1}^{n} \mathrm{mex}(S_i)∑i=1nmex(Si),其中 mex(S)\mathrm{mex}(S)mex(S) 表示不在集合 SSS 中的最小非负整数。例如,在下图中,若设置 a1=3a_1 = 3a1=3,a2=2a_2 = 2a2=2,a3=a4=0a_3 = a_4 = 0a3=a4=0,a5=1a_5 = 1a5=1,则 S1={0,1,2,3}S_1 = \{0,1,2,3\}S1={0,1,2,3},S2={0,1,2}S_2 = \{0,1,2\}S2={0,1,2},S3={0}S_3 = \{0\}S3={0},S4={0}S_4 = \{0\}S4={0},S5={1}S_5 = \{1\}S5={1},树的价值为 4+3+1+1+0=94 + 3 + 1 + 1 + 0 = 94+3+1+1+0=9。
:::align{center}

:::
你需要求出,在所有权值设置方案中,树的价值的最大值。
输入格式
本题包含多组测试数据。
输入的第一行包含一个正整数 ttt,表示测试数据组数。
接下来依次输入每组测试数据,对于每组测试数据:
- 第一行包含两个正整数 n,mn, mn,m,分别表示结点数量与高度的上界。
- 第二行包含 n−1n - 1n−1 个正整数 p2,p3,…,pnp_2, p_3, \ldots, p_np2,p3,…,pn,分别表示每个结点的父亲结点。
输出格式
对于每组测试数据,输出一行一个非负整数,表示树的价值的最大值。
输入输出样例 #1
输入 #1
2
5 2
1 1 2 2
7 2
1 1 2 2 2 3
输出 #1
9
13
说明/提示
【样例 1 解释】
该样例共包含两组测试数据。
对于第一组测试数据,可以设置 a1=3a_1 = 3a1=3,a2=2a_2 = 2a2=2,a3=a4=0a_3 = a_4 = 0a3=a4=0,a5=1a_5 = 1a5=1,则树的价值为 4+3+1+1+0=94 + 3 + 1 + 1 + 0 = 94+3+1+1+0=9。
对于第二组测试数据,可以设置 a1=4a_1 = 4a1=4,a2=3a_2 = 3a2=3,a4=2a_4 = 2a4=2,a3=a6=1a_3 = a_6 = 1a3=a6=1,a5=a7=0a_5 = a_7 = 0a5=a7=0,则树的价值为 5+4+2+0+1+0+1=135 + 4 + 2 + 0 + 1 + 0 + 1 = 135+4+2+0+1+0+1=13。
【样例 2】
见选手目录下的 tree/tree2.in 与 tree/tree2.ans。
该样例满足测试点 3,43,43,4 的约束条件。
【样例 3】
见选手目录下的 tree/tree3.in 与 tree/tree3.ans。
该样例满足测试点 7,87,87,8 的约束条件。
【样例 4】
见选手目录下的 tree/tree4.in 与 tree/tree4.ans。
该样例满足测试点 13,1413,1413,14 的约束条件。
【样例 5】
见选手目录下的 tree/tree5.in 与 tree/tree5.ans。
该样例满足测试点 18,1918,1918,19 的约束条件。
【数据范围】
对于所有测试数据,均有:
- 1≤t≤51 \le t \le 51≤t≤5;
- 2≤n≤8,0002 \le n \le 8,0002≤n≤8,000,1≤m≤min(n−1,800)1 \le m \le \min(n - 1, 800)1≤m≤min(n−1,800);
- 对于所有 2≤i≤n2 \le i \le n2≤i≤n,均有 1≤pi≤i−11 \le p_i \le i - 11≤pi≤i−1;
- 给定的有根树的高度不超过 mmm。
::cute-table{tuack}
| 测试点编号 | n≤n \len≤ | m≤m \lem≤ |
|---|---|---|
| 1,21,21,2 | 777 | n−1n-1n−1 |
| 3,43,43,4 | 131313 | ^ |
| 5,65,65,6 | 181818 | ^ |
| 7,87,87,8 | 404040 | ^ |
| 9,109,109,10 | 120120120 | ^ |
| 11,1211,1211,12 | 360360360 | ^ |
| 13,1413,1413,14 | 4,0004{,}0004,000 | 222 |
| 15∼1715\sim 1715∼17 | ^ | 101010 |
| 18,1918,1918,19 | ^ | 505050 |
| 20∼2520\sim 2520∼25 | 8,0008{,}0008,000 | 800800800 |
代码
#include<bits/stdc++.h>
using namespace std;
int t,n,m,p[8005],f[8005][805],g[8005][805],a2[805][8005],d[8005],siz[8005],df[8005],dn[8005],de[8005],op=0;
vector<int> v[8005];
inline int lb(int a1){
return a1&(-a1);
}
inline void ci(int a1,int b1,int v1){
while(b1<=n){
a2[a1][b1]+=v1;
b1+=lb(b1);
}
return ;
}
inline int co(int a1,int b1){
int c1=0;
while(b1>=1){
c1+=a2[a1][b1];
b1-=lb(b1);
}
return c1;
}
inline void abc(int a1){
siz[a1]=1;
df[a1]=++op;
dn[op]=a1;
for(int tt:v[a1]){
d[tt]=d[a1]+1;
abc(tt);
siz[a1]+=siz[tt];
}
de[a1]=op;
for(int i=1;i<=d[a1];i++){
f[a1][i]=g[a1][i]=i;
for(int tt:v[a1]){
g[a1][i]+=g[tt][i];
}
for(int tt:v[a1]){
f[a1][i]=max(f[a1][i],f[tt][i+1]+g[a1][i]-g[tt][i]);
}
for(int tt:v[a1]){
ci(i,df[tt],g[a1][i]-g[tt][i]);
ci(i,de[tt]+1,g[tt][i]-g[a1][i]);
}
}
for(int j=df[a1]+1;j<=de[a1];j++){
int i=d[dn[j]]-d[a1]+1;
g[a1][i-1]=max(g[a1][i-1],co(i-1,j)+f[dn[j]][i]);
}
return ;
}
int main(){
cin>>t;
while(t--){
cin>>n>>m;
for(int i=1;i<=n;i++){
v[i].clear();
}
for(int i=2;i<=n;i++){
cin>>p[i];
v[p[i]].push_back(i);
}
//cout<<"MLE"<<endl;
memset(a2,0,sizeof(a2));
d[1]=1;
op=0;
//cout<<"TLE"<<endl;
abc(1);
cout<<f[1][1]<<endl;
}
return 0;
}

浙公网安备 33010602011771号