题目大意:

一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w

我们将以下面的形式来要求你对这棵树完成一些操作:

I. CHANGE u t : 把结点u的权值改为t

II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值

III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身

思路:

树链剖分

衣服都不穿的

搞到线段树里,然后维护维护

背一背代码

 #include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#define inf 2139062143
#define ll long long
#define MAXN 30101
#define MOD
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-;ch=getchar();}
while(isdigit(ch)) {x=x*+ch-'';ch=getchar();}
return x*f;
}
int n,Cnt,nxt[MAXN*],fst[MAXN],to[MAXN*],val[MAXN];
int fa[MAXN],dep[MAXN],bl[MAXN],cnt[MAXN],hsh[MAXN];
struct data{int mx,sum,l,r;}tr[MAXN*];
void add(int u,int v) {nxt[++Cnt]=fst[u],fst[u]=Cnt,to[Cnt]=v;}
void build(int x)
{
for(int i=fst[x];i;i=nxt[i])
{
if(to[i]==fa[x]) continue;
dep[to[i]]=dep[x]+;
fa[to[i]]=x;
build(to[i]);
cnt[x]+=cnt[to[i]];
}
cnt[x]++;
}
void Build(int x,int chn)
{
int hvs=;hsh[x]=++Cnt,bl[x]=chn;
for(int i=fst[x];i;i=nxt[i])
if(fa[x]!=to[i]&&cnt[hvs]<cnt[to[i]]) hvs=to[i];
if(!hvs) return ;
Build(hvs,chn);
for(int i=fst[x];i;i=nxt[i])
if(fa[x]!=to[i]&&hvs!=to[i]) Build(to[i],to[i]);
}
void s_build(int k,int l,int r)
{
tr[k].l=l,tr[k].r=r;
if(l==r) return ;
int mid=(l+r)>>;
s_build(k<<,l,mid);
s_build(k<<|,mid+,r);
}
void upd(int k,int pos,int x)
{;
int l=tr[k].l,r=tr[k].r;
if(l==r) {tr[k].mx=tr[k].sum=x;return ;}
int mid=(l+r)>>;
if(mid>=pos) upd(k<<,pos,x);
else upd(k<<|,pos,x);
tr[k].mx=max(tr[k<<].mx,tr[k<<|].mx);
tr[k].sum=tr[k<<].sum+tr[k<<|].sum;
}
int q_sum(int k,int a,int b)
{
int l=tr[k].l,r=tr[k].r;
if(l==a&&r==b) return tr[k].sum;
int mid=(l+r)>>;
if(b<=mid) return q_sum(k<<,a,b);
if(a>mid) return q_sum(k<<|,a,b);
else return q_sum(k<<,a,mid)+q_sum(k<<|,mid+,b);
}
int q_mx(int k,int a,int b)
{
int l=tr[k].l,r=tr[k].r;
if(l==a&&r==b) return tr[k].mx;
int mid=(l+r)>>;
if(b<=mid) return q_mx(k<<,a,b);
if(a>mid) return q_mx(k<<|,a,b);
else return max(q_mx(k<<,a,mid),q_mx(k<<|,mid+,b));
}
int main()
{
n=read();int a,b,res;
for(int i=;i<n;i++) {a=read(),b=read();add(a,b);add(b,a);}
for(int i=;i<=n;i++) val[i]=read();fa[]=;
build();Cnt=;
Build(,);
s_build(,,n);
for(int i=;i<=n;i++) upd(,hsh[i],val[i]);
int T=read();
char ch[];
while(T--)
{
scanf("%s",ch);a=read(),b=read();
if(ch[]=='C') {val[a]=b;upd(,hsh[a],b);}
else if(ch[]=='M')
{
res=-inf;
while(bl[a]!=bl[b])
{
if(dep[bl[a]]<dep[bl[b]]) swap(a,b);
res=max(res,q_mx(,hsh[bl[a]],hsh[a]));
a=fa[bl[a]];
}
res=max(res,q_mx(,min(hsh[a],hsh[b]),max(hsh[a],hsh[b])));
printf("%d\n",res);
}
else if(ch[]=='S')
{
res=;
while(bl[a]!=bl[b])
{
if(dep[bl[a]]<dep[bl[b]]) swap(a,b);
res+=q_sum(,hsh[bl[a]],hsh[a]);
a=fa[bl[a]];
}
res+=q_sum(,min(hsh[a],hsh[b]),max(hsh[a],hsh[b]));
printf("%d\n",res);
}
}
}

UPD 2018.9.19

 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<queue>
#define ll long long
#define inf 2147383611
#define MAXN 500100
using namespace std;
inline int read()
{
int x=,f=;
char ch;ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-;ch=getchar();}
while(isdigit(ch)) {x=x*+ch-'';ch=getchar();}
return x*f;
}
int n,cnt,nxt[MAXN<<],fst[MAXN],to[MAXN<<],val[MAXN];
int fa[MAXN],dep[MAXN],bl[MAXN],sz[MAXN],hsh[MAXN],mx[MAXN<<],sum[MAXN<<];
void add(int u,int v) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v;}
void dfs(int x)
{
sz[x]=,dep[x]=dep[fa[x]]+;
for(int i=fst[x];i;i=nxt[i])
if(to[i]!=fa[x]) {fa[to[i]]=x;dfs(to[i]);sz[x]+=sz[to[i]];}
}
void Dfs(int x,int anc)
{
hsh[x]=++cnt,bl[x]=anc;int hvs=;
for(int i=fst[x];i;i=nxt[i])
if(dep[to[i]]>dep[x]&&sz[hvs]<sz[to[i]]) hvs=to[i];
if(!hvs) return ;Dfs(hvs,anc);
for(int i=fst[x];i;i=nxt[i])
if(dep[to[i]]>dep[x]&&to[i]!=hvs) {Dfs(to[i],to[i]);}
}
void mdf(int k,int l,int r,int x,int w)
{
if(l==r) {mx[k]=sum[k]=w;return ;}
int mid=(l+r)>>;
if(x<=mid) mdf(k<<,l,mid,x,w);
else mdf(k<<|,mid+,r,x,w);
mx[k]=max(mx[k<<],mx[k<<|]),sum[k]=sum[k<<]+sum[k<<|];
}
int querys(int k,int l,int r,int a,int b)
{
if(l==a&&r==b) return sum[k];
int mid=(l+r)>>;
if(b<=mid) return querys(k<<,l,mid,a,b);
else if(a>mid) return querys(k<<|,mid+,r,a,b);
else return querys(k<<,l,mid,a,mid)+querys(k<<|,mid+,r,mid+,b);
}
int querym(int k,int l,int r,int a,int b)
{
if(l==a&&r==b) return mx[k];
int mid=(l+r)>>;
if(b<=mid) return querym(k<<,l,mid,a,b);
else if(a>mid) return querym(k<<|,mid+,r,a,b);
else return max(querym(k<<,l,mid,a,mid),querym(k<<|,mid+,r,mid+,b));
}
int main()
{
n=read();int a,b,res,T;char ch[];
for(int i=;i<n;i++) {a=read(),b=read();add(a,b);add(b,a);}
dfs();cnt=;Dfs(,);
for(int i=;i<=n;i++) mdf(,,n,hsh[i],read());
T=read();
while(T--)
{
scanf("%s",ch);a=read(),b=read();
if(ch[]=='C') mdf(,,n,hsh[a],b);
else if(ch[]=='M')
{
res=-inf;
while(bl[a]!=bl[b])
{
if(dep[bl[a]]<dep[bl[b]]) swap(a,b);
res=max(res,querym(,,n,hsh[bl[a]],hsh[a]));
a=fa[bl[a]];
}
res=max(res,querym(,,n,min(hsh[a],hsh[b]),max(hsh[a],hsh[b])));
printf("%d\n",res);
}
else if(ch[]=='S')
{
res=;
while(bl[a]!=bl[b])
{
if(dep[bl[a]]<dep[bl[b]]) swap(a,b);
res+=querys(,,n,hsh[bl[a]],hsh[a]);
a=fa[bl[a]];
}
res+=querys(,,n,min(hsh[a],hsh[b]),max(hsh[a],hsh[b]));
printf("%d\n",res);
}
}
}

bzoj 1036 树的统计Count的更多相关文章

  1. BZOJ 1036 树的统计Count 树链剖分模板题

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1036 题目大意: 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将 ...

  2. [置顶] bzoj 1036 树的统计Count 点权值模板

    树链剖分 点权型可做模板,链路剖分的思想把点hash到线段树的上,然后可通过n*(log(n)*log(n))的复杂度在树上操作,在线段树上能操作的在链路上都能操作. #include<cstd ...

  3. BZOJ - 1036 树的统计Count (LCT)

    LCT试炼题(代码量居然完爆树剖?) #include<bits/stdc++.h> using namespace std; ,inf=0x3f3f3f3f; ],flp[N],n,m, ...

  4. BZOJ - 1036 树的统计Count (树链剖分+线段树)

    题目链接 #include<bits/stdc++.h> using namespace std; typedef long long ll; ,inf=0x3f3f3f3f; ],mx[ ...

  5. BZOJ 1036 树的统计-树链剖分

    [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 12904 Solved: 5191[Submit][Status ...

  6. Codevs 2460 == BZOJ 1036 树的统计

     2460 树的统计 2008年省队选拔赛浙江 时间限制: 2 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 一棵树上有n个节点,编号分别为1 ...

  7. BZOJ 1036 树的统计

    Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. Q ...

  8. HYSBZ 1036 树的统计Count(树链剖分)题解

    思路: 树链剖分,不知道说什么...我连模板都不会用 代码: #include<map> #include<ctime> #include<cmath> #incl ...

  9. BZOJ 1036 树的统计(树链剖分)

    点权树链剖分模板题. # include <cstdio> # include <cstring> # include <cstdlib> # include &l ...

随机推荐

  1. CAD实现文档坐标到视区坐标的转换(com接口Delphi语言)

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 3 ...

  2. 计算机网络(二)--HTTP详解

    Web相关内容都是存储在Web服务器上,Web服务器上使用的是http协议,因此也被成为http服务器.http的client.server构成了万维网的 基本组件 一.资源 1.URI: 统一资源标 ...

  3. 计算机网络篇(前端、HTTP)

    全端工程师需知道的计算机网络知识 一.网络篇-http报文详解 1. 分类 请求报文 响应报文 2. 报文结构 (一).请求报文 一个HTTP请求报文由请求行(request line).请求头部(h ...

  4. python爬取豆瓣小组700+话题加回复啦啦啦python open file with a variable name

    需求:爬取豆瓣小组所有话题(话题title,内容,作者,发布时间),及回复(最佳回复,普通回复,回复_回复,翻页回复,0回复) 解决:1. 先爬取小组下,所有的主题链接,通过定位nextpage翻页获 ...

  5. Python基础-获取当前目录,上级目录,上上级目录

    import os print '***获取当前目录***' print os.getcwd() print os.path.abspath(os.path.dirname(__file__)) pr ...

  6. codechef 写题计划

    此后将查找各种codechef的脑洞题和好题写

  7. 3.6.5 空串与Null串

        空串""是长度为0的字符串.可以调用以下代码检查一个字符串是否为空:                 String s = "greeting";    ...

  8. ebay 如何获取用户token

    1. 首先 配置环境加载依赖的ebay SDK 下载地址 https://go.developer.ebay.com/ebay-sdks 需要在本地仓库安装下面的jar mvn install:ins ...

  9. IIS部署网站只有首页能访问,其他链接失效/运行.net+Access网站-可能原因:IIS未启用32位应用程序模式

    在64位的机子上IIS运行32位的.NET程序 由于64位操作系统不支持Microsoft OLE DB Provider for Jet驱动程 也不支持更早的Microsoft Access Dri ...

  10. [luoguP1417] 烹调方案(背包DP)

    传送门 By tinylic 如果没有b[i]这个属性的话就是明显的01背包问题. 现在考虑相邻的两个物品x,y.假设现在已经耗费p的时间,那么分别列出先做x,y的代价: a[x]-(p+c[x])* ...