原文链接:http://www.cnblogs.com/zhouzhendong/p/8080189.html


题目传送门 - BZOJ3531


题意概括

  一棵树,n个节点,每一个节点两个值,一个颜色,一个权值。

  4种操作:

  1. 修改某一个节点的颜色

  2. 修改某一个节点的权值

  3. 查询两点之间某一颜色的节点最大权值

  4. 查询两点之间某一颜色的节点权值和


题解

  首先闭着眼睛写上树链剖分。

  因为题目里面说了,颜色的值<=100000。

  所以我们马上想到的开100000个线段树。

  那么修改什么的都是log2n的,时间没问题了。

  那么空间显然要炸。

  怎么做——动态开点啊。

  操作涉及的点很少,所以空间复杂度也是(q+n) log n

  然后就水过了、


代码

#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cmath>
using namespace std;
const int N=100005,S=N*2*20;
bool isd(char ch){return '0'<=ch&&ch<='9';}
int read(){
int res=0;
char ch=getchar();
while (!isd(ch))
ch=getchar();
while (isd(ch))
res=res*10+ch-48,ch=getchar();
return res;
}
struct Gragh{
int cnt,y[N*2],nxt[N*2],fst[N];
void clear(){
cnt=0;
memset(fst,0,sizeof fst);
}
void add(int a,int b){
y[++cnt]=b,nxt[cnt]=fst[a],fst[a]=cnt;
}
}g;
int n,q,root[N],w[N],c[N];
int fa[N],son[N],size[N],depth[N],top[N],p[N],ap[N],cnp=0;
int ls[S],rs[S],Max[S],sum[S],tot=0;
void Get_Gen_Info(int rt,int pre,int d){
size[rt]=1,fa[rt]=pre,son[rt]=-1,depth[rt]=d;
for (int i=g.fst[rt];i;i=g.nxt[i])
if (g.y[i]!=pre){
int s=g.y[i];
Get_Gen_Info(s,rt,d+1);
size[rt]+=size[s];
if (son[rt]==-1||size[s]>size[son[rt]])
son[rt]=s;
}
}
void Get_Top(int rt,int tp){
top[rt]=tp;
ap[p[rt]=++cnp]=rt;
if (son[rt]==-1)
return;
Get_Top(son[rt],tp);
for (int i=g.fst[rt];i;i=g.nxt[i]){
int s=g.y[i];
if (s!=fa[rt]&&s!=son[rt])
Get_Top(s,s);
}
}
void pushup(int rt){
Max[rt]=max(Max[ls[rt]],Max[rs[rt]]);
sum[rt]=sum[ls[rt]]+sum[rs[rt]];
}
void change(int &rt,int L,int R,int pos,int v){
if (!rt)
rt=++tot;
if (L==R){
Max[rt]=sum[rt]=v;
return;
}
int mid=(L+R)>>1;
if (pos<=mid)
change(ls[rt],L,mid,pos,v);
else
change(rs[rt],mid+1,R,pos,v);
pushup(rt);
}
int query(int rt,int L,int R,int xL,int xR,int op){
if (!rt||R<xL||L>xR)
return 0;
if (xL<=L&&R<=xR)
return op?Max[rt]:sum[rt];
int mid=(L+R)>>1;
int ansL=query(ls[rt],L,mid,xL,xR,op);
int ansR=query(rs[rt],mid+1,R,xL,xR,op);
return op?max(ansL,ansR):(ansL+ansR);
}
int Tquery(int a,int b,int op){
int f1=top[a],f2=top[b],color=c[a],ans=0;
while (f1!=f2){
if (depth[f1]<depth[f2])
swap(f1,f2),swap(a,b);
int v=query(root[color],1,n,p[f1],p[a],op);
ans=op?max(ans,v):(ans+v);
a=fa[f1],f1=top[a];
}
if (depth[a]>depth[b])
swap(a,b);
int v=query(root[color],1,n,p[a],p[b],op);
ans=op?max(ans,v):(ans+v);
return ans;
}
int main(){
n=read(),q=read();
for (int i=1;i<=n;i++)
w[i]=read(),c[i]=read();
g.clear();
for (int i=1,a,b;i<n;i++){
a=read(),b=read();
g.add(a,b);
g.add(b,a);
}
Get_Gen_Info(1,0,0);
Get_Top(1,1);
for (int i=1;i<=n;i++)
change(root[c[i]],1,n,p[i],w[i]);
for (int i=1;i<=q;i++){
char op[5];
int x,y;
scanf("%s",op);
x=read(),y=read();
if (op[0]=='C'&&op[1]=='C'){
change(root[c[x]],1,n,p[x],0);
change(root[c[x]=y],1,n,p[x],w[x]);
}
if (op[0]=='C'&&op[1]=='W')
change(root[c[x]],1,n,p[x],w[x]=y);
if (op[0]=='Q'&&op[1]=='S')
printf("%d\n",Tquery(x,y,0));
if (op[0]=='Q'&&op[1]=='M')
printf("%d\n",Tquery(x,y,1));
}
return 0;
}

  

BZOJ3531 [Sdoi2014]旅行 树链剖分 线段树的更多相关文章

  1. B20J_3231_[SDOI2014]旅行_树链剖分+线段树

    B20J_3231_[SDOI2014]旅行_树链剖分+线段树 题意: S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,城市信仰不同的宗教,为了方便,我们用不同的正整数代表各种宗教. S国 ...

  2. 洛谷P3313 [SDOI2014]旅行 题解 树链剖分+线段树动态开点

    题目链接:https://www.luogu.org/problem/P3313 这道题目就是树链剖分+线段树动态开点. 然后做这道题目之前我们先来看一道不考虑树链剖分之后完全相同的线段树动态开点的题 ...

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. ROM、PROM、EPROM、EEPROM、FLASH ROM简介

    ROM指的是"只读存储器",即Read-Only Memory.这是一种线路最简单半导体电路,通过掩模工艺, 一次性制造,其中的代码与数据将永久保存(除非坏掉),不能进行修改.这玩 ...

  2. Linux查看所有用户和组信息

    主要通过以下两个命令: cat /etc/passwd cat /etc/group 步骤一:cat /etc/passwd查看所有的用户信息,详情如下图: 步骤2:cat /etc/passwd|g ...

  3. PHPStorm配置Xdebug官方文档

    1 配置Xdebug 下载Xdebug 下载与您的PHP版本兼容的Xdebug扩展,并将其保存在该php/文件夹中. php/文件夹 的位置是在安装PHP引擎期间定义的. 如果您使用的是AMP软件包, ...

  4. JavaScript 输入小数点(event.key或event.code)

    1. 概述 1.1 说明 在开发过程中,有时候需要仅输入数字与小数,故记录下使用过的功能,以便后期使用. 1.2 key 定义:按下按键时返回的标识符,按键标识符是表示键盘按钮的字符串(如1,2,a等 ...

  5. Tornado学习笔记(三) 请求方式/状态码

    本章我们来学习 Tornado 支持的请求方式 请求方式 Tornado支持任何合法的HTTP请求(GET.POST.PUT.DELETE.HEAD.OPTIONS).你可以非常容易地定义上述任一种方 ...

  6. liux三剑客grep 正则匹配

    001正则匹配(大部分需要转义) ‘^‘: 锚定行首 '$' : 锚定行尾 [0-9] 一个数字 [^0-9] 除去数字所有,^出现在[]这里表示取反 [a-z] [A-Z] [a-Z] \s 匹配空 ...

  7. nginx+ssl 服务器 双向认证

    项目后台服务器采用nginx+tomcat 负载均衡架构  不久 访问协议有http升级为https 对服务器认证采用沃通的ssl证书 nginx ssl证书安装 参照沃通官方文档 他们有技术支持沟通 ...

  8. Confluence 6 数据库问题解除

    有关数据库相关的问题,请参考 Database Troubleshooting 中的内容. 希望获得更多的帮助,请参考 Troubleshooting Problems and Requesting ...

  9. Linux 用户(user)和用户组(group)管理概述

    一.理解Linux的单用户多任务,多用户多任务概念: Linux 是一个多用户.多任务的操作系统:我们应该了解单用户多任务和多用户多任务的概念: 1.Linux 的单用户多任务:单用户多任务:比如我们 ...

  10. tomcat 报错处理

    一.tomcat报错找不到资源集市 原因:tomcat的配置文件sever.xml 里的 docbase配置被Eclispe修改了 解决方法:修改回来 <Context docBase=&quo ...