List wants to travel

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 429    Accepted Submission(s): 92

Problem Description
A boy named List who is perfect in English. Now he wants to travel and he is making a plan. But the cost of living in same citie always changes. Now he wants to know how many different kinds of continuous same cost he has to pay for living between two cities. Can you help him? (He is so lazy to do this by himself.)
 
Input
There are multiple cases. The first line contains two positive numbers N and M(N (N<=40000) where N is the amount of cities and M (M<=50000)) is the amount of operations.Then N-1 lines where each line have 3 integers a b and c, representing that there is a bidirectionoal road between city a and city b, and the cost is c.(a != b and c <= 100000). Then there are M lines of operation. For example, "Change a b c" means changing all the costs of the road which are passed by him when he travels from city a to city b to c. "Query a b" means he wants you to tell him how many different kinds of continuous same cost he has to pay traveling from city a to city b.(if a == b, the cost is 0).
 
Output
He insure you that there is exactly one route between every two different cities.
 
Sample Input
9 3
1 2 2
2 3 1
1 7 2
1 4 2
3 5 2
3 6 1
5 8 2
5 9 3
Query 1 8
Change 2 6 3
Query 1 6
 
Sample Output
3
2
 
Source
/*
hdu 5893 (树链剖分+合并) problem:
1.update:将a->b的边权设置为c
2.query:求a->b的连续边权的个数
222333 -> 2 22112->3 solve:
主要是查询的意思不是很懂. how many different kinds of continuous same cost
以为不同还要分长度,数值大小什么的。 于是没怎么想
结果后来发现是求区间中有多少个连续的子区间 - -. 感觉很僵
update直接用一个标记解决
query的时候, 维护区间左右端点的值以合并区间,合并的时候注意维护子区间的数量
而且树链剖分时 在合并链的时候也要进行判断什么的.
update的u == v的时候最好判断一下, 否则查询son[u] -> v会有问题
我们只有一个重链,可能有很多的轻链,query的 u == v时就是轻链合并的情况.
总体都是线段树的思路 hhh-2016-09-19 22:36:11
*/
#pragma comment(linker,"/STACK:124000000,124000000")
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <vector>
#include <map>
#define lson i<<1
#define rson i<<1|1
#define ll long long
#define clr(a,b) memset(a,b,sizeof(a))
#define key_val ch[ch[root][1]][0]
using namespace std;
const int maxn = 200100;
const int inf = 0x3f3f3f3f;
int head[maxn],tot,pos,son[maxn];
int top[maxn],fp[maxn],fa[maxn],dep[maxn],num[maxn],p[maxn];
int n;
int a[maxn];
struct Edge
{
int to,next;
int w;
} edge[maxn<<2]; void ini()
{
tot = 0,pos = 1;
clr(head,-1),clr(son,-1);
clr(a,0);
} void add_edge(int u,int v,int w)
{
edge[tot].to = v,edge[tot].next = head[u],edge[tot].w = w,head[u] = tot++;
} void dfs1(int u,int pre,int d)
{
// cout << u << " " <<pre <<" " <<d <<endl;
dep[u] = d;
fa[u] = pre,num[u] = 1;
for(int i = head[u]; ~i; i = edge[i].next)
{
int v = edge[i].to;
if(v != pre)
{
a[v] = edge[i].w;
dfs1(v,u,d+1);
num[u] += num[v];
if(son[u] == -1 || num[v] > num[son[u]])
son[u] = v;
}
}
} void getpos(int u,int sp)
{
top[u] = sp;
p[u] = pos++;
fp[p[u]] = u;
if(son[u] == -1)return ;
getpos(son[u],sp);
for(int i = head[u]; ~i ; i = edge[i].next)
{
int v = edge[i].to;
if(v != son[u] && v != fa[u])
getpos(v,v);
}
} struct node
{
int l,r,mid;
int ls,rs,same;
ll num ;
} tree[maxn << 2]; void push_up(int i)
{ if(tree[lson].rs == tree[rson].ls )
{
tree[i].num = tree[lson].num + tree[rson].num -1;
}
else
tree[i].num =tree[lson].num + tree[rson].num;
tree[i].ls = tree[lson].ls;
tree[i].rs = tree[rson].rs;
} void build(int i,int l,int r)
{
tree[i].l = l,tree[i].r = r;
tree[i].mid=(l+r) >>1;
tree[i].same = inf;
tree[i].num = tree[i].ls = tree[i].rs = 0;
if(l == r)
{
tree[i].ls = tree[i].rs = a[fp[l]];
tree[i].num = 1;
// cout << fp[l] <<" " << a[fp[l]] <<endl;
return;
}
build(lson,l,tree[i].mid);
build(rson,tree[i].mid+1,r);
push_up(i);
}
void make_same(int i,int val)
{
tree[i].same = val;
tree[i].num = 1;
tree[i].ls = tree[i].rs = val;
}
void push_down(int i)
{
if(tree[i].same != inf)
{
make_same(lson,tree[i].same);
make_same(rson,tree[i].same);
tree[i].same = inf;
}
} void update_area(int i,int l,int r,int val)
{
if(tree[i].l >= l && tree[i].r <= r)
{
tree[i].same = val;
tree[i].num = 1;
tree[i].ls = tree[i].rs = val;
return ;
}
push_down(i);
int mid = tree[i].mid;
if(l <= mid)
update_area(lson,l,r,val);
if(r > mid)
update_area(rson,l,r,val);
push_up(i);
} ll query(int i,int l,int r,int &tls,int &trs)
{
if(tree[i].l >= l && tree[i].r <= r)
{
if(tree[i].l == l)
tls = tree[i].ls;
if(tree[i].r == r)
trs = tree[i].rs;
return tree[i].num ;
}
push_down(i);
int mid = tree[i].mid ;
ll ans = 0;
if(r <= mid)
ans = query(lson,l,r,tls,trs);
else if(l > mid)
ans = query(rson,l,r,tls,trs);
else
{
int tls1,tls2,trs1,trs2;
ll t1 = query(lson,l,mid,tls1,trs1);
ll t2 = query(rson,mid+1,r,tls2,trs2);
ans = t1 + t2;
if(tree[lson].rs == tree[rson].ls)
{
ans --;
}
tls = tls1,trs = trs2;
}
push_up(i);
return ans;
} void update_same(int u,int v,int val)
{
int f1 = top[u],f2 = top[v];
while(f1 != f2)
{
if(dep[f1] < dep[f2])
{
swap(f1,f2),swap(u,v);
}
update_area(1,p[f1],p[u],val);
u = fa[f1],f1 = top[u];
}
if(u == v)
return ;
if(dep[u] > dep[v]) swap(u,v);
update_area(1,p[son[u]],p[v],val);
} ll query_dif(int u,int v)
{
int f1 = top[u],f2 = top[v];
int ls1,rs1,ls2,rs2;
ls1 = rs1 = ls2 = rs2 = inf;
int tls1,trs1,tls2,trs2;
int fi1 = 1,fi2 = 1;
ll ans = 0;
while(f1 != f2)
{
if(dep[f1] > dep[f2])
{
ans += query(1,p[f1],p[u],tls1,trs1);
if(trs1 == ls1)
ans--;
ls1 = tls1;
if(fi1)
{
rs1 = trs1;
fi1 = 0;
}
u = fa[f1],f1 = top[u];
}
else
{
ans += query(1,p[f2],p[v],tls2,trs2);
if(trs2 == ls2)
ans--;
ls2 = tls2;
if(fi2)
{
rs2 = trs2;
fi2 = 0;
}
v = fa[f2],f2 = top[v];
}
}
if(u == v)
{
if(tls1 == tls2)
ans --;
return ans;
}
if(dep[u] > dep[v])
{
ans += query(1,p[son[v]],p[u],tls1,trs1);
if(trs1 == ls1)
ans--;
if(tls1 == ls2)
ans --;
}
else
{
ans += query(1,p[son[u]],p[v],tls2,trs2);
if(trs2 == ls2)
ans--;
if(tls2 == ls1)
ans--;
}
return ans;
}
char str[10];
int main()
{
// freopen("in.txt","r",stdin);
int a,b,c;
int m,u,v,w;
while(scanf("%d%d",&n,&m) != EOF)
{
ini();
for(int i =1; i <n; i++)
{
scanf("%d%d%d",&u,&v,&w);
add_edge(u,v,w);
add_edge(v,u,w);
}
dfs1(1,0,0);
getpos(1,1);
build(1,1,pos-1);
// cout << pos -1 <<endl;
for(int i = 1; i <= m; i++)
{
scanf("%s",str);
scanf("%d%d",&a,&b);
if(str[0] == 'C')
{
scanf("%d",&c);
update_same(a,b,c);
}
else
{
if(a == b)
printf("0\n");
else
printf("%I64d\n",query_dif(a,b));
}
}
}
return 0;
}

  

hdu 5893 (树链剖分+合并)的更多相关文章

  1. hdu 5052 树链剖分

    Yaoge’s maximum profit Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/ ...

  2. hdu 4897 树链剖分(重轻链)

    Little Devil I Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others ...

  3. hdu 5274 树链剖分

    Dylans loves tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Othe ...

  4. HDU 5052 /// 树链剖分+线段树区间合并

    题目大意: 给定n (表示树有n个结点) 接下来n行给定n个点的点权(在这个点上买鸡或者卖鸡的价钱就是点权) 接下来n-1行每行给定 x y 表示x结点和y结点之间有一条边 给定q (表示有q个询问) ...

  5. HDU 3966 (树链剖分+线段树)

    Problem Aragorn's Story (HDU 3966) 题目大意 给定一颗树,有点权. 要求支持两种操作,将一条路径上的所有点权值增加或减少ai,询问某点的权值. 解题分析 树链剖分模板 ...

  6. hdu 3966(树链剖分+线段树区间更新)

    传送门:Problem 3966 https://www.cnblogs.com/violet-acmer/p/9711441.html 学习资料: [1]线段树区间更新:https://blog.c ...

  7. HDU 5242 树链剖分思想的贪心

    题意及博客 树链剖分分为2步,第一次求出深度,重儿子,第二次求出重链,用到了启发式的思想,即对于比较重的儿子,尽量去完整的维护它.类似于我们去合并两个堆,明显把小的堆逐个插入大的堆中会比大的往小的插更 ...

  8. HDU 3966 /// 树链剖分+树状数组

    题意: http://acm.hdu.edu.cn/showproblem.php?pid=3966 给一棵树,并给定各个点权的值,然后有3种操作: I x y z : 把x到y的路径上的所有点权值加 ...

  9. hdu 4729 树链剖分

    思路:这个树链剖分其实还是比较明显的.将边按权值排序后插入线段树,然后用线段树查找区间中比某个数小的数和,以及这样的数的个数.当A<=B时,就全部建新的管子. 对于A>B的情况比较 建一条 ...

随机推荐

  1. 掌握SQLServer锁的相关概念

    一.为什么要引入锁 当多个用户同时对数据库的并发操作时会带来以下数据不一致的问题: ◆丢失更新 A,B两个用户读同一数据并进行修改,其中一个用户的修改结果破坏了另一个修改的结果,比如订票系统 ◆脏读 ...

  2. 1013团队Beta冲刺day7

    项目进展 李明皇 今天解决的进度 部分数据传递和使用逻辑测试 林翔 今天解决的进度 服务器端查看个人发布的action,修改已发布消息状态的action,仍在尝试使用第三方云存储功能保存图片 孙敏铭 ...

  3. Python 实现火车票查询工具

    注意:由于 12306 的接口经常变化,课程内容可能很快过期,如果遇到接口问题,需要根据最新的接口对代码进行适当修改才可以完成实验. 一.实验简介 当你想查询一下火车票信息的时候,你还在上 12306 ...

  4. 【iOS】Swift if let 和 if var

    if let unwrappedOptional = postDict { print("The optional has a value! It's \(unwrappedOptional ...

  5. 根据HTML5的新方法 drag & drop 方法实现表格拖拽实例

    上一次学习了html5的drag和drop方法,传送门  就自己写了个例子加深自己对drag和drop的理解.不过一开始不是很简单,遇到了不少问题.还好网络万能的,什么都能查到,总算完成了. 说明和详 ...

  6. webapi 使用Autofac 开发经历

    2018/4/6 号 早上五点..被手机震动吵醒. 之后直接打开电脑,打算再加强下我自己的webapi这套东西. 虽然三年的工作经验接触了N多框架和各种风格的开发方式,但是让我自己来搞一套实在不会搞, ...

  7. HDFS文件读写操作(基础基础超基础)

    环境 OS: Ubuntu 16.04 64-Bit JDK: 1.7.0_80 64-Bit Hadoop: 2.6.5 原理 <权威指南>有两张图,下次po上来好好聊一下 实测 读操作 ...

  8. 快速获取表单多条数据,使用ajax传递给后台

    当表单中有多条数据需要向后台传递时,一个一个的获取显然是不可取的办法,可以借助表单的serialize()方法获取. HTML: <form id="form"> &l ...

  9. linux下执行java类(运行java定时器)

    假如有一个定时器TimerTest.java import java.io.IOException; import java.util.Timer; public class TimerTest { ...

  10. js控制表格实时编辑

    点击添加,在表格的最后一行添加一行表单元素,右侧按钮变为保存和取消.(点击保存,数据用ajax无刷新添加到界面,点击取消,取消此行的添加.)点击编辑,在本行改为表单,带有原来的值,右侧按钮变为确认和取 ...