NWERC 2013 - J (codeforces gym - 100405J)
题目描述:给你一颗二叉树,保证每个点要么是叶子节点,要么有左右两个儿子。某些叶子节点上放着灯,请你移动最少的灯,使得整棵树平衡
对平衡的定义:对于树上的每个点左右儿子中灯数的差的绝对值≤1,那么这棵树平衡。总灯数sum≤1000.
解题思路:题目中强调的是移动,不能往里面添加,也不能从树中拿走。这个移动操作就给我们造成了一些困难,起初想一些dp的方法,感觉都不是很靠谱。
于是看了官方题解,题解中用了一步巧妙地转化,然后递归求解,很有借鉴意义。
首先对于移动操作次数最少,我们可以转化成,往树里插入sum个点,尽量把点放入本来有灯的位置,最大覆盖多少个的问题。那么原来没有灯,现在要放点,这些位置的个数就是答案。
完成这一步转化之后就要挖掘题目性质,绝对值差1这个性质十分重要,因为这近似于一步二分,也就是如果我们从顶点开始递归地往下放,那么最多进行logSUM层就能使得剩下的 可放点数达到0或1,这就使我们得到一种很可行的分治求解的方法:Get(x, cnt)表示向x这个点插入cnt个灯,向空点放的情况最少有多少个(也就是移动次数最少有多少次)。对于cnt是偶数的情况,就直接Get(x.left, cnt >> 1), Get(x.right, cnt >> 1), 而对于cnt是奇数,就要讨论一下左右放多放少这两种情况,取个min了。
递归的终止条件:①cnt == 0,返回0 ②x == 0 && cnt > 0返回INF(无解)③cnt == 1 子树中本来有灯返回1,无灯返回0
P.S.题目中并没有给总点数,经过分析总点数不会超过叶子节点的二倍。但是题目读入比较繁琐,字符串长度要开至少4000。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std; const int MaxN = ;
const int INF = ;
struct Node {
int left, right, father;
int cLoc, cOn;
}tree[MaxN + ];
int n, tot, ans;
char s[MaxN * + ]; void Init()
{
memset(tree, , sizeof(tree));
int len = strlen(s);
int p = ; n = ;
for (int i = ; i < len; i++) {
if (s[i] == '(') {
if (tree[p].left == ) tree[p].left = ++n;
else tree[p].right = ++n;
tree[n].father = p;
p = n;
}
else if (s[i] == 'B') {
tree[p].cOn = ;
tree[p].cLoc = ;
p = tree[p].father;
i++;
}
else {
int L = tree[p].left;
int R = tree[p].right;
tree[p].cOn = tree[L].cOn + tree[R].cOn;
tree[p].cLoc = tree[L].cLoc + tree[R].cLoc;
if (tree[p].cLoc == ) tree[p].cLoc = ;
p = tree[p].father;
}
}
//for (int i = 1; i <= n; i++) printf("%d %d %d\n", i, tree[i].cOn, tree[i].cLoc);
} int Get(int x, int cnt)
{
if (cnt == ) return ;
if (x == ) return INF;
if (cnt == ) return (int)(tree[x].cOn == );
if (cnt & ) {
int cL1 = Get(tree[x].left, cnt >> );
int cR1 = Get(tree[x].right, cnt - (cnt >> ));
int cL2 = Get(tree[x].left, cnt - (cnt >> ));
int cR2 = Get(tree[x].right, cnt >> );
return min(cL1 + cR1, cL2 + cR2);
}
else {
int cL = Get(tree[x].left, cnt >> );
int cR = Get(tree[x].right, cnt >> );
return cL + cR;
}
} int main()
{
while (~scanf("%s", s)) {
Init();
ans = Get(, tree[].cOn);
if (ans >= INF) printf("impossible\n");
else printf("%d\n", ans);
}
}
NWERC 2013 - J (codeforces gym - 100405J)的更多相关文章
- Codeforces gym 101343 J.Husam and the Broken Present 2【状压dp】
2017 JUST Programming Contest 2.0 题目链接:Codeforces gym 101343 J.Husam and the Broken Present 2 J. Hu ...
- Codeforces GYM 100876 J - Buying roads 题解
Codeforces GYM 100876 J - Buying roads 题解 才不是因为有了图床来测试一下呢,哼( 题意 给你\(N\)个点,\(M\)条带权边的无向图,选出\(K\)条边,使得 ...
- Codeforces Gym 101623A - 动态规划
题目传送门 传送门 题目大意 给定一个长度为$n$的序列,要求划分成最少的段数,然后将这些段排序使得新序列单调不减. 考虑将相邻的相等的数缩成一个数. 假设没有分成了$n$段,考虑最少能够减少多少划分 ...
- CodeForces Gym 100213F Counterfeit Money
CodeForces Gym题目页面传送门 有\(1\)个\(n1\times m1\)的字符矩阵\(a\)和\(1\)个\(n2\times m2\)的字符矩阵\(b\),求\(a,b\)的最大公共 ...
- Codeforces Gym 101252D&&floyd判圈算法学习笔记
一句话题意:x0=1,xi+1=(Axi+xi%B)%C,如果x序列中存在最早的两个相同的元素,输出第二次出现的位置,若在2e7内无解则输出-1. 题解:都不到100天就AFO了才来学这floyd判圈 ...
- Codeforces Gym 101190M Mole Tunnels - 费用流
题目传送门 传送门 题目大意 $m$只鼹鼠有$n$个巢穴,$n - 1$条长度为$1$的通道将它们连通且第$i(i > 1)$个巢穴与第$\left\lfloor \frac{i}{2}\rig ...
- 【Codeforces Gym 100725K】Key Insertion
Codeforces Gym 100725K 题意:给定一个初始全0的序列,然后给\(n\)个查询,每一次调用\(Insert(L_i,i)\),其中\(Insert(L,K)\)表示在第L位插入K, ...
- codeforces gym 100553I
codeforces gym 100553I solution 令a[i]表示位置i的船的编号 研究可以发现,应是从中间开始,往两边跳.... 于是就是一个点往两边的最长下降子序列之和减一 魔改树状数 ...
- codeforces Gym 100187J J. Deck Shuffling dfs
J. Deck Shuffling Time Limit: 2 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100187/pro ...
随机推荐
- poj3349找相同的雪花(哈希)
题目传送门 题目大意:给你n个雪花,每个雪花的六个棱都有各自的长度,如果存在两片雪花的每条棱长度对应相同,则输出一句英文,如果不存在就输出另外一句英文,n和长度都比较大. 思路:第一次真正接触哈希,查 ...
- Educational Codeforces Round 7 A
Description Consider the infinite sequence of integers: 1, 1, 2, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4, 5. ...
- linux中firewall与iptables防火墙服务
火墙firewall-cmd --state 查看火墙的状态firewall-cmd --get-active-zones 目前所处的域firewall-cmd --get-default-zone ...
- Sublime Text 3 3126 安装+注册码
首先,到官网下载且安装,个人是安装版本的 https://www.sublimetext.com/3 接着,写入注册码.2016/11/26 亲测有效 —– BEGIN LICENSE —– Mich ...
- java在window系统的一些问题
一般的, 在windows cmd上启动 utf-8编码的java应用 会有一些字符集问题 可以修改cmd的字符集编码为utf8 , chcp 65001 java -D有空格时 区别: VM参数是 ...
- 转发 django 初探
https://www.cnblogs.com/franknihao/p/7682914.html https://blog.csdn.net/tang_jin2015/article/details ...
- RTT之内存管理及异常中断
内存管理分静态内存管理和动态内存管理(根据大小又分2种) 静态内存管理:创建.删除.初始化.解绑.申请和释放.初始化内存池是属于静态内存管理,与创建内存池不同的是,此处内存池对象所使用的内存空间是由用 ...
- sysbench测试MySQL筛选tps
log=$1tps_array=`awk -F '[,:]' '{print $4}' ${log}`zero=0 for tps in ${tps_array}do tps=`echo ${tps} ...
- SimpleAdapter与listview,gridview的组合用法
首先要明白SimpleAdapter构造方法的几个参数的含义: public SimpleAdapter(Context context, List<? extends Map<Strin ...
- (转)awk数组详解及企业实战案例
awk数组详解及企业实战案例 原文:http://www.cnblogs.com/hackerer/p/5365967.html#_label03.打印数组:1. [root@nfs-server t ...