[ABC263F] Tournament 题解
[ABC263F] Tournament Solution
更好的阅读体验戳此进入
题面
给定
Solution
挺有意思的一道题,不难但是需要一点智慧。
显然 DP,但 DP 的状态有多种均可,这里主要介绍一个写起来较为简单易懂的。
令
发现这个东西和朴素线段树十分相似,则对于满二叉树的叶子节点编号
所以对于所有叶子节点有
显然最终答案在根节点且剩余的比赛次数为
不难发现这个东西通过记忆化搜索来实现会更便捷一些。
Code
#define _USE_MATH_DEFINES
#include <bits/stdc++.h>
#define PI M_PI
#define E M_E
#define npt nullptr
#define SON i->to
#define OPNEW void* operator new(size_t)
#define ROPNEW(arr) void* Edge::operator new(size_t){static Edge* P = arr; return P++;}
using namespace std;
mt19937 rnd(random_device{}());
int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
bool rnddd(int x){return rndd(1, 100) <= x;}
typedef unsigned int uint;
typedef unsigned long long unll;
typedef long long ll;
typedef long double ld;
#define LS (p << 1)
#define RS (LS | 1)
#define MID ((gl + gr) >> 1)
template < typename T = int >
inline T read(void);
int N, powN;
ll dp[(1 << 16) << 2][20];
ll C[(1 << 16) + 10][20];
ll MakeDP(int p, int i){
if(~dp[p][i])return dp[p][i];
if(p >= N)return dp[p][i] = C[(p ^ N) + 1][i];
return dp[p][i] = max(MakeDP(LS, i + 1) + MakeDP(RS, 0), MakeDP(LS, 0) + MakeDP(RS, i + 1));
}
int main(){
memset(dp, -1, sizeof dp);
N = 1 << (powN = read());
for(int i = 1; i <= N; ++i)for(int j = 1; j <= powN; ++j)C[i][j] = read();
printf("%lld\n", MakeDP(1, 0));
fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
return 0;
}
template < typename T >
inline T read(void){
T ret(0);
int flag(1);
char c = getchar();
while(c != '-' && !isdigit(c))c = getchar();
if(c == '-')flag = -1, c = getchar();
while(isdigit(c)){
ret *= 10;
ret += int(c - '0');
c = getchar();
}
ret *= flag;
return ret;
}
UPD
update-2022_12_30 初稿
本文作者:Tsawke
本文链接:https://www.cnblogs.com/tsawke/p/17032804.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
分类:
ABC
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步