poj 2763 Housewife Wind : 树链剖分维护边 O(nlogn)建树 O((logn)²)修改与查询
/**
problem: http://poj.org/problem?id=2763
**/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<vector>
using namespace std; const int MAXN = ; template <typename T>
class SegmentTree {
private:
struct Node {
int left, right;
T sum, lazy;
} node[MAXN << ];
T data[MAXN];
void pushUp(int root) {
node[root].sum = node[root << ].sum + node[root << | ].sum;
}
void pushDown(int root) {
if(node[root].left == node[root].right) return;
int lson = root << ;
int rson = root << | ;
node[lson].sum = node[root].lazy * (node[lson].right - node[lson].left + );
node[rson].sum = node[root].lazy * (node[rson].right - node[rson].left + );
node[lson].lazy = node[root].lazy;
node[rson].lazy = node[root].lazy;
node[root].lazy = ;
}
public:
void build(int left, int right, int root = ) {
node[root].left = left;
node[root].right = right;
node[root].lazy = ;
if(left == right) {
node[root].sum = data[left];
} else {
int mid = (left + right) >> ;
build(left, mid, root << );
build(mid + , right, root << | );
pushUp(root);
}
}
void update(int left, int right, T value, int root = ) {
int lson = root << ;
int rson = root << | ;
if(node[root].lazy) pushDown(root);
if(node[root].left == left && node[root].right == right) {
node[root].sum = value * (right - left + );
node[root].lazy = value;
return ;
}
if(left >= node[rson].left) {
update(left, right, value, rson);
} else if(right <= node[lson].right) {
update(left, right, value, lson);
} else {
update(left, node[lson].right, value, lson);
update(node[rson].left, right, value, rson);
}
pushUp(root);
}
T query(int left, int right, int root = ) {
int lson = root << ;
int rson = root << | ;
if(node[root].lazy) pushDown(root);
if(node[root].left == left && node[root].right == right) {
return node[root].sum;
}
if(left >= node[rson].left) {
return query(left, right, rson);
} else if(right <= node[lson].right) {
return query(left, right, lson);
} else {
return query(left, node[lson].right, lson) + query(node[rson].left, right, rson);
}
}
void clear(int n, const vector<int> &d) {
for(int i = ; i <= n; i ++) {
this->data[i] = d[i];
}
build(, n);
}
}; template <typename T>
class TreeToLink {
private:
struct Point {
int size, son, depth, father, top, newId;
T data;
} point[MAXN];
struct Edge {
int to, next;
} edge[MAXN << ];
int oldId[MAXN], first[MAXN], sign, sumOfPoint, cnt;
SegmentTree<T> st;
void dfs1(int u, int father = , int depth = ) {
point[u].depth = depth;
point[u].father = father;
point[u].size = ;
int maxson = -;
for(int i = first[u]; i != -; i = edge[i].next) {
int to = edge[i].to;
if(to == father) continue;
dfs1(to, u, depth + );
point[u].size += point[to].size;
if(point[to].size > maxson) {
point[u].son = to;
maxson = point[to].size;
}
}
}
void dfs2(int u, int top) {
point[u].newId = ++cnt;
oldId[cnt] = u;
point[u].top = top;
if(point[u].son == -) {
return ;
}
dfs2(point[u].son, top);
for(int i = first[u]; i != -; i = edge[i].next) {
int to = edge[i].to;
if(to == point[u].son || to == point[u].father) continue;
dfs2(to, to);
}
}
public:
void clear(int n) {
sumOfPoint = n;
sign = ;
cnt = ;
for(int i = ; i <= n; i ++) {
first[i] = -;
point[i].son = -;
// scanf("%d", &point[i].data); // input
point[i].data = ;
}
}
void addEdgeOneWay(int u, int v) {
edge[sign].to = v;
edge[sign].next = first[u];
first[u] = sign ++;
}
void addEdgeTwoWay(int u, int v) {
addEdgeOneWay(u, v);
addEdgeOneWay(v, u);
}
void preWork(int x = ) {
dfs1(x);
dfs2(x, x);
vector<int> data(sumOfPoint + );
for(int i = ; i <= sumOfPoint; i ++) {
data[i] = point[oldId[i]].data;
}
st.clear(sumOfPoint, data);
}
void updatePath(int x, int y, T z){
while(point[x].top != point[y].top){
if(point[point[x].top].depth < point[point[y].top].depth)
swap(x, y);
st.update(point[point[x].top].newId, point[x].newId, z);
x = point[point[x].top].father;
}
if(point[x].depth > point[y].depth)
swap(x, y);
st.update(point[x].newId, point[y].newId, z);
}
T queryPath(int x, int y){
T ans = ;
while(point[x].top != point[y].top){
if(point[point[x].top].depth < point[point[y].top].depth)
swap(x, y);
ans += st.query(point[point[x].top].newId, point[x].newId);
x = point[point[x].top].father;
}
if(x == y) return ans; // Edge
if(point[x].depth > point[y].depth)
swap(x, y);
// ans += st.query(point[x].newId, point[y].newId); // Point
ans += st.query(point[point[x].son].newId, point[y].newId); // Edge
return ans;
}
void updateSon(int x, T z){
st.update(point[x].newId, point[x].newId + point[x].size - , z);
}
T querySon(int x){
return st.query(point[x].newId, point[x].newId + point[x].size - );
}
T queryPoint(int x) {
return queryPath(x, x);
}
void updatePoint(int x, T z) {
updatePath(x, x, z);
}
bool deeper(int u, int v){
return point[u].depth > point[v].depth;
}
}; class Solution {
private:
int n, q, s;
TreeToLink<int> ttl;
struct Edge{
int u, v, w;
}edge[MAXN];
public:
void solve() {
scanf("%d%d%d", &n, &q, &s);
ttl.clear(n);
for(int i = ; i < n; i ++){
scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].w);
ttl.addEdgeTwoWay(edge[i].u, edge[i].v);
}
ttl.preWork(s);
for(int i = ; i < n; i ++){
if(ttl.deeper(edge[i].u, edge[i].v)){
swap(edge[i].u, edge[i].v);
}
ttl.updatePoint(edge[i].v, edge[i].w);
}
int now = s;
for(int i = , a, b, c; i < q; i ++){
scanf("%d%d", &a, &b);
if(a == ){
scanf("%d", &c);
ttl.updatePoint(edge[b].v, c);
}else{
printf("%d\n", ttl.queryPath(now, b));
now = b;
}
}
}
} DarkScoCu; int main() {
DarkScoCu.solve();
return ;
}
poj 2763 Housewife Wind : 树链剖分维护边 O(nlogn)建树 O((logn)²)修改与查询的更多相关文章
- POJ - 2763 Housewife Wind (树链剖分/ LCA+RMQ+树状数组)
题意:有一棵树,每条边给定初始权值.一个人从s点出发.支持两种操作:修改一条边的权值:求从当前位置到点u的最短路径. 分析:就是在边可以修改的情况下求树上最短路.如果不带修改的话,用RMQ预处理LCA ...
- POJ 2763 Housewife Wind (树链剖分 有修改单边权)
题目链接:http://poj.org/problem?id=2763 n个节点的树上知道了每条边权,然后有两种操作:0操作是输出 当前节点到 x节点的最短距离,并移动到 x 节点位置:1操作是第i条 ...
- poj 2763 Housewife Wind(树链拆分)
id=2763" target="_blank" style="">题目链接:poj 2763 Housewife Wind 题目大意:给定一棵 ...
- POJ 2763 Housewife Wind 树链拋分
一.前言 这破题WA了一天,最后重构还是WA,最后通过POJ讨论版得到的数据显示,我看上去是把某个变量写错了..于是,还是低级错误背锅啊....代码能力有待进一步提升2333333 二.题意 某家庭主 ...
- POJ2763 Housewife Wind 树链剖分 边权
POJ2763 Housewife Wind 树链剖分 边权 传送门:http://poj.org/problem?id=2763 题意: n个点的,n-1条边,有边权 修改单边边权 询问 输出 当前 ...
- poj 2763(RMQ+BIT\树链剖分)
传送门:Problem 2763 https://www.cnblogs.com/violet-acmer/p/9686774.html 题意: 一对夫妇居住在xx村庄,小屋之间有双向可达的道路,不会 ...
- hdu 3966 Aragorn's Story : 树链剖分 O(nlogn)建树 O((logn)²)修改与查询
/** problem: http://acm.hdu.edu.cn/showproblem.php?pid=3966 裸板 **/ #include<stdio.h> #include& ...
- POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 )
POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 ) 题意分析 给出n个点,m个询问,和当前位置pos. 先给出n-1条边,u->v以及边权w. 然后有m个询问 ...
- POJ 2763 Housewife Wind LCA转RMQ+时间戳+线段树成段更新
题目来源:POJ 2763 Housewife Wind 题意:给你一棵树 2种操作0 x 求当前点到x的最短路 然后当前的位置为x; 1 i x 将第i条边的权值置为x 思路:树上两点u, v距离为 ...
随机推荐
- 对于在gti操作遇见detached Head时
1.什么是detached HEAD 在git中,这是一个处于”游离“状态的标签 2.使用git branch <new_branch_name> <HEAD_code> 为这 ...
- CSS3图片边框
CSS3图片边框 顾名思义就是为边框应用背景图片,它和我们常用的background属性比较相似,语法规则:
- linux 安装和卸载软件
安装: apt-get install cups-pdf 卸载:apt -get remove cups
- jQuery Event.stopImmediatePropagation() 函数详解
stopImmediatePropagation()函数用于阻止剩余的事件处理函数的执行,并防止当前事件在DOM树上冒泡. 根据DOM事件流机制,在元素上触发的大多数事件都会冒泡传递到该元素的所有祖辈 ...
- 【Python自然语言处理】第一章学习笔记——搜索文本、计数统计和字符串链表
这本书主要是基于Python和一个自然语言工具包(Natural Language Toolkit, NLTK)的开源库进行讲解 NLTK 介绍:NLTK是一个构建Python程序以处理人类语言数据的 ...
- win7 下vs2008试用版破解
用过微软的开发套件Visual Studio 2008,如果用的是试用版本,超过90天,就会过期,出现下面这张图片显示的 下面介绍破解的步骤: 1.首先打开控制面板——然后找到卸载或更改程序——然后找 ...
- Third week-homework(员工管理系统)
需求: 可以查询员工所有信息 可以修改员工信息 可以增加新员工 code: import sys,json # yuangong = { # "1": ["faker&q ...
- March 4 2017 Week 10 Saturday
There is more to life than increasing its speed. 生活不仅仅是匆匆赶路. I always think I have walked very slowl ...
- STM32-F429ZIT6-开发流程
---恢复内容开始--- 一.开发环境搭建 1.编译器安装破解 2.STM32Cube MX安装 3.驱动安装 4.固件库安装 二.硬件准备 1.PC 2.STM32开发板 3.下载线 三.资料准备 ...
- Android(java)学习笔记25:Android 手机拨号
1. 手机拨号程序:(只有程序代码) package cn.itcast.phone; import android.app.Activity; import android.content.Inte ...