【学术篇】SPOJ-DISQUERY
一道傻逼链剖我TM总共差不多写了一小时,调了将近一天!!!!!!
题目传送门:http://www.spoj.com/problems/DISQUERY/
嗯,偷偷递小广告:SPOJ是个挺好的OJ (因为可以交BF和WhiteSpace代码)
从里面见到了很多没见过的语言(尽管根据提交记录来讲好像也没什么人用2333)
然后再%%%一下评论区里1A的dalao… 我真是调跪了…(我还是太弱了orz)
题目大意:
给一棵树,每次询问x->y之间的路径上边权最大和最小的边.
心路历程:
这TM不就一道傻逼链剖么…
且慢,好像是边权? 那下放到点权不就完了么= =
(我真的以为自己是对的)
然后就用了半小时打了个链剖板子,然后……不出所料,死递归了…
然后就各种调试(由于DEV-C++显示莫名爆炸,所以用的VS2015调试,非常爽啊),发现自己max min都能打反也是人才…
然后发现下放之后1号节点(根)不好处理啊,加了个特判,乱搞了一波,就过了样例2啊…
然后样例1带进去怎么做都不对啊,以为是自己代码的问题,又debug然后各种乱搞,但是怎么折腾都不对,再一步一步调,发现一切都在按照自己想象的进行?
于是打开神器mspaint画了个图,发现下放点权不行啊….
于是以为自己写了半天的代码算是废了,但是咋做呢?
就去问了问dalao(感谢这位不愿透露姓名(其实是我不想打TA名字2333)的dalao)
然后dalao告诉我连x->y边的时候可以拆成x->z->y的两条边啊,然后把边权放在z就可以了~~
就茅塞顿开了.
回头又改了改代码然后又死递归了,发现自己的线段树操作都是1,1,n所以会越界,所以就动态改了n(懒得改线段树的代码,好容易才debug的没啥问题),结果有些地方的n又不行所以开了两个变量…
最后终于过了所有的样例…
然后交上去RE了,因为加虚拟点的话点数会翻倍…只开N的数组是不行的….
就把N改成了200000就A了(并没看内存限制,真是幸运呢~)
嗯 综上所述,这题就是一道傻逼链剖但是我更傻逼到不会处理所以就调了这么长时间= =
讲个笑话我第一遍打的链剖板子就是对的但是由于过不了样例我还怀疑了好久正确性并debug了不知道多少遍orz….
唉
代码:
#include <cstdio>
const int N = 200010;
const int F = ~0U >> 1;
inline int max(const int &a, const int &b) {
if (a < b) return b; return a;
}
inline int min(const int &a, const int &b) {
if (a < b) return a; return b;
}
inline int getnum() {
int a = 0; char c = getchar(); bool f = 0;
for (; (c<'0' || c>'9') && c != '-'; c = getchar());
if (c == '0') c = getchar(), f = 1;
for (; c >= '0'&&c <= '9'; c = getchar()) a = (a << 1) + (a << 3) + c - '0';
if (f) return -a; return a;
}
int w[N], n, m;
int fa[N], d[N], sz[N], ez[N];
int top[N], pos[N], rank[N], ti;
struct edge {
int to, next;
}e[N << 1]; int v[N], tot;
void buildedge(int x, int y) {
e[++tot].to = y; e[tot].next = v[x]; v[x] = tot;
e[++tot].to = x; e[tot].next = v[y]; v[y] = tot;
}
struct node {
int bn, sn;
}t[N << 2];
void dfs1(int x) {
sz[x] = 1; ez[x] = x;
for (int i = v[x]; i; i = e[i].next) {
int y = e[i].to;
if (!d[y]) {
d[y] = d[x] + 1;
dfs1(y);
fa[y] = x;
sz[x] += sz[y];
if (ez[x] == x || sz[y] > sz[ez[x]])
ez[x] = y;
}
}
}
void dfs2(int x, int tp) {
pos[++ti] = x; rank[x] = ti; top[x] = tp;
if (ez[x] != x) dfs2(ez[x], tp);
for (int i = v[x]; i; i = e[i].next) {
int y = e[i].to;
if (d[y] == d[x] + 1 && y != ez[x])
dfs2(y, y);
}
}
void update(int x) {
t[x].sn = min(t[x << 1].sn, t[x << 1 | 1].sn);
t[x].bn = max(t[x << 1].bn, t[x << 1 | 1].bn);
}
void build(int x, int l, int r) {
if (l == r) {
int id = pos[++ti];
if (id <= m) t[x].sn = F, t[x].bn = -F;
else t[x].sn = t[x].bn = w[id];
//唯一要交代的可能就是这样的处理了,为了防止实际节点的点权影响到结果(比如设为0可能会影响到最小值),我们把实际节点的最大值设为无穷小,最小值设为无穷大即可...
return;
}
int mid = (l + r) >> 1;
build(x << 1, l, mid);
build(x << 1 | 1, mid + 1, r);
update(x);
}
int query_min(int x, int l, int r, int L, int R) {
if (L <= l&&r <= R) return t[x].sn;
int mid = (l + r) >> 1, ans = F;
if (L <= mid) ans = min(ans, query_min(x << 1, l, mid, L, R));
if (R > mid) ans = min(ans, query_min(x << 1 | 1, mid + 1, r, L, R));
return ans;
}
int query_max(int x, int l, int r, int L, int R) {
if (L <= l&&r <= R) return t[x].bn;
int mid = (l + r) >> 1, ans = -F;
if (L <= mid) ans = max(ans, query_max(x << 1, l, mid, L, R));
if (R > mid) ans = max(ans, query_max(x << 1 | 1, mid + 1, r, L, R));
return ans;
}
void query(int x, int y, int &mins, int &maxs) {
int bs = -F, ss = F;
while (top[x] != top[y]) {
if (d[top[x]] > d[top[y]]) {
bs = max(bs, query_max(1, 1, n, rank[top[x]], rank[x]));
ss = min(ss, query_min(1, 1, n, rank[top[x]], rank[x]));
x = fa[top[x]];
}
else {
bs = max(bs, query_max(1, 1, n, rank[top[y]], rank[y]));
ss = min(ss, query_min(1, 1, n, rank[top[y]], rank[y]));
y = fa[top[y]];
}
}
if (d[x] < d[y]) {
bs = max(bs, query_max(1, 1, n, rank[x], rank[y]));
ss = min(ss, query_min(1, 1, n, rank[x], rank[y]));
}
else{
bs = max(bs, query_max(1, 1, n, rank[y], rank[x]));
ss = min(ss, query_min(1, 1, n, rank[y], rank[x]));
}
mins = ss; maxs = bs;
}
int main() {
m = getnum(); n = m;
for (int i = 1; i < m; i++) {
int a = getnum(), b = getnum(), c = getnum();
buildedge(a, ++n); buildedge(n, b); w[n] = c;
}
d[1] = 1; dfs1(1); dfs2(1, 1); ti = 0; build(1, 1, n);
int k = getnum();
for (int i = 1; i <= k; i++) {
int a = getnum(), b = getnum(), ans1, ans2;
query(a, b, ans1, ans2);
printf("%d %d\n", ans1, ans2);
}
}
反正就这样吧…