有趣的构造 Continuous City
一道有趣的构造题。
原有的题解都只讲了构造方法,没有做其它说明,看上去不明不白的,所以搞懂后自己写一篇。讲得比较详细。
情况一
那么如果不是恰好的
我们原来的图显然有这样一个性质,那就是从开始的节点到每一个节点
那问题来了,这样一来我们就没有长度为
改为
但对于最大的一位,前面没有东西了,这样一连有一条长度为
对于上面那副图,若我们的输入是
(省略了
情况三
用情况二构造一个
代码
需要处理一些节点编号与幂之间关系的细节。
#include <cstdio>
#include <vector>
int L, R;
struct twt { int u, v, c; };
std::vector<twt> edge;
void add(int u, int v, int c) { edge.push_back((twt){u, v, c}); }
int solve(int L, int R) {
if(L > 1) { // 情况三
int n = solve(1, R-L+1);
add(n, n+1, L-1);
return n+1;
}
if((R & -R) == R) { // ex情况一
int k = 0, R_ = R;
while(R_) R_ /= 2, k++;
k--;
add(1, 2, 1);
for(int i = 3; i <= k+2; i++) {
add(1, i, 1);
for(int j = 2; j < i; j++) add(j, i, (1 << (j-2)));
}
return k+2;
}
int n = 0; // 情况二
while(1 << (n+1) <= R-1) n++;
solve(1, 1 << n);
add(1, n+3, 1);
for(int i = 0; i <= n; i++)
if((R-1) >> i & 1)
add(i+2, n+3, 1 + ((R - 1) >> (i + 1) << (i + 1)));
return n+3;
}
int main() {
scanf("%d%d", &L, &R);
puts("YES");
int n = solve(L, R);
printf("%d %d\n", n, (signed)edge.size());
for(int i = 0; i < (signed)edge.size(); i++) printf("%d %d %d\n", edge[i].u, edge[i].v, edge[i].c);
}