第23届四川省大学生联赛(J题)
题目导航:https://codeforces.com/gym/105910
int main() { int T; cin >> T; while (T--) { int n; cin >> n; int haveans = 0; int all = 0; int du[1000010]; int sd[1000010]; for (int i = 1; i <= n; i++) { cin >> du[i]; all += du[i]; if (!haveans) { if (i == 1) { sd[i] = du[i]; } else { sd[i] = sd[i - 1] + (du[i] - 1); } if (sd[i] < i && i != n) { cout << "No" << endl; haveans = 1; } } } if (haveans == 0 && all != 2 * (n - 1)) { cout << "No" << endl; haveans = 1; } if (!haveans) { cout << "Yes" << endl; } } return 0; }
代码如上……虽然这是一道没什么算法含金量的简单题但是昨天卡得我……忒难受
第一次思路是从叶子往根节点(从下向上)推,每次遇到一个叶子,就寻找比它的度大且大的幅度最小的父节点,为了保证爸爸总比儿子的序数要小,所以还要寻找比这个叶子序数要小的最大父节点。。
如咱们所见思路有点太复杂了,虽然说勉强给它码出来了但是1e6的数据量必超时(GPT跟我说用线段树优化,,去它的线段树)
*这个思路主要的毛病在于不确定父节点是谁,为了找到爸爸,不得不嵌套循环,导致了O(n^2),甚至还糟,————
于是反过来想,能不能从上往下推捏?因为爸爸一定序数小,所以从1开始逐个枚举,一定就是从上往下的顺序。然后每个节点拿到之后,计算目前的节点们所有的儿子席位减去目前所有节点数量(因为它们自己也会占据一些儿子席位),那么剩余的儿子席位就可以新加节点进来,
注意,节点1的所有度数都可以算作儿子席位,而后面的任何数的儿子席位都是度数-1,因为有一个度数是它爸爸占据的。
【【不是这么简单的题你都能卡……】】001111001??:》,》“而且居然还能写这么长的题解出来???

浙公网安备 33010602011771号