【学术篇】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);
}
}
反正就这样吧…
【学术篇】SPOJ-DISQUERY的更多相关文章
- 【学术篇】SPOJ GEN Text Generator AC自动机+矩阵快速幂
还有5天省选才开始点字符串这棵技能树是不是太晚了点... ~题目の传送门~ AC自动机不想讲了QAQ.其实很久以前是学过然后打过板子的, 但也仅限于打过板子了~ 之前莫名其妙学了一个指针版的但是好像不 ...
- 【学术篇】SPOJ FTOUR2 点分治
淀粉质入门第一道 (现在个人认为spoj比bzoj要好_(:з」∠)_ 关于点分治的话推荐去看一看漆子超的论文>>>这里这里<<< 之前一直试图入点分治坑, 但是因 ...
- 【学术篇】SPOJ QTREE 树链剖分
发现链剖这东西好久不写想一遍写对是有难度的.. 果然是熟能生巧吧.. WC的dalao们都回来了 然后就用WC的毒瘤题荼毒了我们一波, 本来想打个T1 44分暴力 然后好像是特判写挂了还是怎么的就只能 ...
- 【学术篇】SPOJ COT 树上主席树
这是学完主席树去写的第二道题_(:з」∠)_ 之前用树上莫队水过了COT2... 其实COT也可以用树上莫队水过去不过好像复杂度要带个log还是怎么样可能会被卡常数.. 那就orz主席吧.... 写了 ...
- 【学术篇】一些水的不行的dp
最近做了几道非常水非常水的dp...... 之后刷的一些水dp也会写在这里...... 此篇题目难度不递增!!! Emmmm....... 1.luogu1043数字游戏 以前看过这个题几遍,没做这个 ...
- 【学术篇】51nod 1238 最小公倍数之和
这是一道杜教筛的入(du)门(liu)题目... 题目大意 求 \[ \sum_{i=1}^n\sum_{j=1}^nlcm(i,j) \] 一看就是辣鸡反演一类的题目, 那就化式子呗.. \[ \s ...
- 【学术篇】luogu2184贪婪大陆
题目在这里哦, 戳一下就可以了~ 题目大意: 支持两种操作,区间添加一种新元素,查询区间颜色种数.. 题目标签是线段树啊,我也本来想写一个线段树,后来写不出来……(我太弱了orz) 然后就草率地看了看 ...
- 【学术篇】oj.jzxx.net2701 无根树
这是一道来自OIerBBS的题目.. 原帖地址:http://www.oierbbs.com/forum.php?mod=viewthread&tid=512?fromuid=71 (似乎是个 ...
- SPOJ DISQUERY LCA + 倍增
裸题,如此之水- Code: #include<cstdio> #include<algorithm> using namespace std; const int maxn ...
随机推荐
- NX二次开发-NXOPEN将工程图转成PDF文件
NX9+VS2012 #include <uf.h> #include <uf_draw.h> #include <NXOpen/PrintPDFBuilder.hxx& ...
- Java-Class-@I:org.apache.ibatis.annotations.Mapper
ylbtech-Java-Class-@I:org.apache.ibatis.annotations.Mapper 1.返回顶部 2.返回顶部 1. package com.ylbtech.ed ...
- Python实现字符串与数组相互转换功能示例
Python实现字符串与数组相互转换功能示例 本文实例讲述了Python实现字符串与数组相互转换功能.分享给大家供大家参考,具体如下: 字符串转数组 str = '1,2,3' arr = s ...
- maven-version
<java.version>1.8</java.version><project.build.sourceEncoding>UTF-8</project.bu ...
- 剑指offer——14机器人的运动范围
题目描述 地上有一个m行和n列的方格.一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子. 例如,当k为18时,机器人能 ...
- <pygame> 打飞机(小游戏)
0.游戏的基本实现 ''' 游戏的基本实现 游戏的初始化:设置游戏窗口,绘制图像的初始位置,设定游戏时钟 游戏循环:设置刷新频率,检测用户交互,更新所有图像位置,更新屏幕显示 ''' 1.安装pyga ...
- 2-JDK环境变量配置和验证
背景: 官网下载,默认路径安装,如下图,java目录下有两个文件夹:jdk和jre: 1.计算机 -> 右击 -> 属性 -> 选择左侧的'高级系统设置' 2.高级系统设置 -> ...
- iOS逆向系列-动态调试
Xcode调试App原理 Mac安装了Xcode Xcode的安装包中包含了debugserver 可执行类型的Mach-O文件,iPhone第一次连接Xcode调试会将Xcode中的debugser ...
- html编写的日历
1.html (1) <html> <head> <meta http-equiv="Content-Type" content="text ...
- PHP算法之两数相加
给出两个 非空 的链表用来表示两个非负的整数.其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字. 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和 ...