2016shenyang-1002-HDU5893-List wants to travel-树链剖分+线段树维护不同区间段个数
肯定先无脑树链剖分,然后线段树维护一段区间不同个数,再维护一个左右端点的费用。
线段树更新,pushDown,pushUp的时候要注意考虑链接位置的费用是否相同
还有就是树链剖分操作的时候,维护上一个更新的位置的费用。
总之就是出现区间合并,就考虑总数是否要减一
好想不好写
//场上根本写不完啊
/*--------------------------------------------------------------------------------------*/ #include <algorithm>
#include <iostream>
#include <cstring>
#include <ctype.h>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <string>
#include <queue>
#include <stack>
#include <cmath>
#include <set>
#include <map> //debug function for a N*M array
#define debug_map(N,M,G) printf("\n");for(int i=0;i<(N);i++)\
{for(int j=;j<(M);j++){\
printf("%d",G[i][j]);}printf("\n");}
//debug function for int,float,double,etc.
#define debug_var(X) cout<<#X"="<<X<<endl;
#define LL long long
const int INF = 0x3f3f3f3f;
const LL LLINF = 0x3f3f3f3f3f3f3f3f;
/*--------------------------------------------------------------------------------------*/
using namespace std; int N,M,T;
const int maxn = 2e5+; struct Edge{
int x,y,val;
}e[maxn]; vector <int> G[maxn]; int val[maxn],dep[maxn],siz[maxn],top[maxn],id[maxn],son[maxn],fa[maxn];
int topw; void init()
{
for(int i=;i<maxn;i++) G[i].clear();
topw = ;
} void dfs_1(int u,int f,int d)
{
fa[u] = f;
son[u] = ;
siz[u] = ;
dep[u] = d;
for(int i=;i<G[u].size();i++) if(G[u][i] != f)
{
dfs_1(G[u][i],u,d+);
siz[u] += siz[G[u][i]];
if(siz[son[u]] < siz[G[u][i] ])
{
son[u] = G[u][i];
}
}
} void dfs_2(int u,int tp)
{
top[u] = tp;
id[u] = ++topw;
if(son[u]) dfs_2(son[u],tp);
for(int i=;i<G[u].size();i++) if(G[u][i]!=fa[u] && G[u][i] != son[u] )
{
dfs_2(G[u][i],G[u][i]);
}
} void debug()
{
for(int i=;i<=N;i++)
{
printf("%d siz:%d son:%d dep:%d fa:%d ",i,siz[i],son[i],dep[i],fa[i]);
printf("top:%d id:%d\n",top[i],id[i]);
}
return ;
} /*-----------------------------------*/
#define lson(x) (x<<1)
#define rson(x) (x<<1|1) struct SegmentTree{
int l,r;
int lazy;
int num,lcost,rcost;
}segtree[*maxn]; void pushUp(int x)
{
segtree[x].num = segtree[lson(x)].num + segtree[rson(x)].num - (segtree[lson(x)].rcost==segtree[rson(x)].lcost? : );
segtree[x].lcost = segtree[lson(x)].lcost;
segtree[x].rcost = segtree[rson(x)].rcost;
//printf("x:%d [%d,%d] num:%d\n",x,segtree[x].l,segtree[x].r,segtree[x].num);
//printf("lcost:%d rcost:%d\n",segtree[x].lcost,segtree[x].rcost);
//printf("l->rcost:%d r->lcost:%d\n",segtree[lson(x)].rcost,segtree[rson(x)].lcost);
} void pushDown(int x)
{
if(segtree[x].lazy != -)
{
segtree[lson(x)].lcost = segtree[lson(x)].rcost = segtree[x].lazy;
segtree[rson(x)].lcost = segtree[rson(x)].rcost = segtree[x].lazy;
segtree[lson(x)].num = segtree[rson(x)].num = ;
segtree[lson(x)].lazy = segtree[rson(x)].lazy = segtree[x].lazy;
segtree[x].lazy = -;
}
} void Build(int l,int r,int x)
{
segtree[x].l = l;
segtree[x].r = r;
segtree[x].lazy = -;
if(l == r)
{
segtree[x].num = ;
segtree[x].lcost = segtree[x].rcost = val[l];
return ;
}
int mid = (l+r)>>;
Build(l,mid,lson(x));
Build(mid+,r,rson(x));
pushUp(x);
} void update(int x,int L,int R,int cost)
{
if(segtree[x].l >= L && segtree[x].r <= R)
{
segtree[x].lcost = segtree[x].rcost = cost;
segtree[x].num = ;
segtree[x].lazy = cost;
return ;
}
pushDown(x);
int mid = (segtree[x].l + segtree[x].r) >> ;
if(L <= mid) update(lson(x),L,R,cost);
if(R > mid) update(rson(x),L,R,cost);
pushUp(x);
return ;
} int query(int x,int L,int R)
{
if(segtree[x].l >= L && segtree[x].r <= R)
{
return segtree[x].num;
}
pushDown(x);
int mid = (segtree[x].l + segtree[x].r) >> ;
int ans = ; if(R <= mid) ans = query(lson(x),L,R);
else if(L > mid) ans = query(rson(x),L,R);
else ans = query(lson(x),L,R) + query(rson(x),L,R) - (segtree[lson(x)].rcost==segtree[rson(x)].lcost ? : ) ;
pushUp(x);
return ans;
} int query_edge(int x,int pos)
{
if(segtree[x].l == segtree[x].r)
{
return segtree[x].lcost;
}
pushDown(x);
int res = ;
int mid = (segtree[x].l + segtree[x].r) >> ;
if(pos <= mid) res = query_edge(lson(x),pos);
else res = query_edge(rson(x),pos);
pushUp(x);
return res ;
} int Find(int u,int v)
{
int ans = ,fu = top[u],fv = top[v];
int last_u=- , last_v = -;
int last_u_color,last_v_color;
//printf("%d->%d\n",u,v); while(fu != fv)
{
if(dep[fu] < dep[fv])
{
swap(fu,fv);swap(u,v);
swap(last_u,last_v);
swap(last_u_color,last_v_color);
} //printf("query:[%d,%d] %d->%d ",id[fu],id[u],u,fu);
//printf("%d\n",query(1,id[fu],id[u]));
ans += query(,id[fu],id[u]);
if(last_u == -)
{
last_u = fu;
last_u_color = query_edge(,id[fu]);
}
else
{
if(last_u != - && fa[last_u] == u)
{
//printf("u sub:%d\n",(last_u_color==query_edge(1,id[u]) ? 1 : 0));
ans -= (last_u_color==query_edge(,id[u]) ? : );
last_u = fu;
last_u_color = query_edge(,id[fu]);
}
}
u = fa[fu];
fu = top[u];
}
if(u == v)
{
if(last_u != - && last_v != - && last_u_color==last_v_color) ans -= ;
return ans;
}
if(dep[u] < dep[v])
{
swap(u,v);
swap(last_u,last_v);
swap(last_u_color,last_v_color);
}
//printf("query:[%d,%d] %d->%d ",id[son[v]],id[u],u,son[v]);
ans += query(,id[son[v] ],id[u]);
//printf("%d*\n",query(1,id[son[v]],id[u])); //printf("last_u:%d last_v:%d\n",last_u,last_v);
if(last_u != - && fa[last_u] == u)
{
//printf("u sub:%d last_u_color:%d u_color:%d\n",(last_u_color==query_edge(1,id[u]) ? 1 : 0),last_u_color,query_edge(1,id[u]));
ans -= (last_u_color==query_edge(,id[u]) ? : );
last_u = fu;
last_u_color = query_edge(,id[u]);
} if(last_v != - && fa[last_v] == v)
{
//printf("v sub:%d last_v_color:%d son[v]_color:%d\n",(last_v_color==query_edge(1,id[son[v]]) ? 1 : 0),last_v_color,query_edge(1,id[son[v]] ));
ans -= (last_v_color==query_edge(,id[son[v]]) ? : );
last_v = fv;
last_v_color = query_edge(,id[son[v]]);
} return ans;
} void Change(int u,int v,int cost)
{
int fu = top[u],fv = top[v];
//printf("%d->%d\n",u,v);
while(fu != fv)
{
if(dep[fu] < dep[fv])
{
swap(fu,fv);swap(u,v);
}
//printf("change:[%d,%d] %d->%d %d\n",id[fu],id[u],u,fu,cost);
update(,id[fu],id[u],cost);
u = fa[fu];
fu = top[u];
}
if(u == v) return ;
if(dep[u] < dep[v]) swap(u,v);
//printf("change:[%d,%d] %d->%d %d\n",id[son[v]],id[u],u,son[u],cost);
update(,id[son[v]],id[u],cost);
return ;
} int main()
{
//freopen("input","r",stdin);
while(~scanf("%d%d",&N,&M))
{
init();
int u,v,w;
for(int i=;i<N;i++)
{
scanf("%d%d%d",&u,&v,&w);
e[i].x = u;e[i].y = v;e[i].val = w;
G[u].push_back(v);
G[v].push_back(u);
}
topw = ;
dfs_1(,,);
dfs_2(,);
//debug();
for(int i=;i<N;i++)
{
if(dep[e[i].x] < dep[e[i].y]) swap(e[i].x,e[i].y);
val[id[e[i].x]] = e[i].val;
} Build(,topw,);
char op[];
//printf("-----------------\n");
for(int i=;i<M;i++)
{
scanf("%s",op);
if(op[] == 'Q')
{
scanf("%d%d",&u,&v);
printf("%d\n",Find(u,v));
}
else
{
scanf("%d%d%d",&u,&v,&w);
Change(u,v,w);
}
//puts("");
}
}
}
2016shenyang-1002-HDU5893-List wants to travel-树链剖分+线段树维护不同区间段个数的更多相关文章
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1153 Solved: 421[Submit][Statu ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- BZOJ2243 (树链剖分+线段树)
Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...
- POJ3237 (树链剖分+线段树)
Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...
- bzoj4034 (树链剖分+线段树)
Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...
- HDU4897 (树链剖分+线段树)
Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...
- Aizu 2450 Do use segment tree 树链剖分+线段树
Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...
- 【POJ3237】Tree(树链剖分+线段树)
Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...
- HDU 2460 Network(双连通+树链剖分+线段树)
HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...
- bzoj2243[SDOI2011]染色 树链剖分+线段树
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 9012 Solved: 3375[Submit][Status ...
随机推荐
- Ubuntu/Windows双系统修复引导
Ubuntu/Windows双系统修复引导 首先说明:在Windows存在的前提下安装Ubuntu(或者Ubuntu系列)是不需要修复引导的.因为grub会自动搜索存在硬盘中的系统. 而在Ub ...
- XML语言基础1
这学期选修了XML技术这门课,没有发课本,于是参考了W3school教程,整理一下上课的内容. 1.XML简介 XML是一种标记语言,很类似HTML,它不是对HTML的替代,而是对HTML的补充.在大 ...
- python之装饰器
一.简单装饰器: #定义装饰器函数 def W1(main_func): def outer(): print("before") main_func() print(" ...
- 好久没有写博客了,发现Live Writer也更新了
最近由于工作变动,工作内容和心态也有所变化,所以很久没有写博客了,而且我的开源项目深蓝词库转换也很近没有更新了.今天打开LiveWriter发现居然有新版本,于是果断更新.现在新的LiveWriter ...
- 【hadoop】——修改hadoop FileUtil.java,解决权限检查的问题
在Hadoop Eclipse开发环境搭建这篇文章中,第15.)中提到权限相关的异常,如下: 15/01/30 10:08:17 WARN util.NativeCodeLoader: Unable ...
- 大型网站的 HTTPS 实践(1):HTTPS 协议和原理
转自:http://op.baidu.com/2015/04/https-s01a01/ 1 前言 百度已经于近日上线了全站 HTTPS 的安全搜索,默认会将 HTTP 请求跳转成 HTTPS.本文重 ...
- DataTable去除重复行,根据某一字段进行distinct
网上有很多方法,比如利用视图处理: //去掉重复行 DataView dv = table.DefaultView; table = dv.ToTable(true, new string[] { & ...
- 正则表达式(/[^0-9]/g,'')中的"/g"是什么意思?
解答“正则表达式(/[^0-9]/g,'')中的"/g"是什么意思?”这个问题,也为了能够便于大家对正则表达式有一个更为综合和深刻的认识,我将一些关键点和容易犯糊涂的地方再系统总结 ...
- 时光煮雨 Unity3d 序列目标点的移动①
系列目录 [Unity3D基础]让物体动起来①--基于UGUI的鼠标点击移动 [Unity3D基础]让物体动起来②--UGUI鼠标点击逐帧移动 时光煮雨 Unity3D让物体动起来③—UGUI DoT ...
- Vim插件管理——Vundle
Vim插件管理--Vundle 都说Vim时程序员写给自己的编辑器,其中的情结可想而知.身为一只程序狗CodingDoge,今天就让我带各位学习Vim的使用. vim因为其庞大而强劲的插件受到无比的推 ...