肯定先无脑树链剖分,然后线段树维护一段区间不同个数,再维护一个左右端点的费用。

线段树更新,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-树链剖分+线段树维护不同区间段个数的更多相关文章

  1. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  2. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

  3. BZOJ2243 (树链剖分+线段树)

    Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...

  4. POJ3237 (树链剖分+线段树)

    Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...

  5. bzoj4034 (树链剖分+线段树)

    Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...

  6. HDU4897 (树链剖分+线段树)

    Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...

  7. 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 ...

  8. 【POJ3237】Tree(树链剖分+线段树)

    Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...

  9. HDU 2460 Network(双连通+树链剖分+线段树)

    HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...

  10. bzoj2243[SDOI2011]染色 树链剖分+线段树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 9012  Solved: 3375[Submit][Status ...

随机推荐

  1. a标签加入单击事件 屏蔽href跳转页面

    我们常用的在a标签中有点击事件:1. a href="javascript:js_method();" 这是我们平台上常用的方法,但是这种方法在传递this等参数的时候很容易出问题 ...

  2. 《内容生产向视频过渡:Facebook收购QuickFire意欲何为?》有感

    1月9日消息,Facebook周四表示,已收购位于加州圣迭戈的QuickFire Networks. 一.解决视频传输问题 QuickFire是一家开发视频内容发布设备和转码处理软件的创业公司,其创办 ...

  3. Maven基础配置--nexus私服配置

    登录nexus私服后台,按照下图1-3的顺序进行添加仓库: 其中步骤3有三种仓库类型(Type)进行选择 1. Hosted Repository:本地仓库,在私服服务器上存放用户自行上传的jar包: ...

  4. SQLServer修改字段类型

    Alter table [表名] Alter column [列名] [列类型]

  5. Access restriction: The type 'RSACipher' is not API

    解决方法: http://stackoverflow.com/questions/860187/access-restriction-on-class-due-to-restriction-on-re ...

  6. Using Confluent’s JDBC Connector without installing the entire platform

    转自:https://prefrontaldump.wordpress.com/2016/05/02/using-confluents-jdbc-connector-without-installin ...

  7. 使用 python 发送邮件

    1.使用python 写发邮箱代码: def sendmail (): import smtplib from email.mime.text import MIMEText from email.u ...

  8. 2------------NLPIR(ICTCLAS2016)分词系统添加用户词典功能

    备注:win7 64位系统,netbeans编程 基本代码框架参见我的另一篇文章:NLPIR分词功能 代码实现: package cwordseg; import java.io.Unsupporte ...

  9. Javascript为元素添加事件处理函数

    document.getElementById("test").onclick = function(){ ... };

  10. sql查询一天内的where写法,sql写法

    sql查询一天内的写法: 1. where createtime BETWEEN (select date_format(now(),'%Y-%m-%d 00:00:00')) and (select ...