潇爷昨天刚刚讲完。。。感觉得还可以。。。对着模板打了个模板。。。还是不喜欢用指针。。。。

1036: [ZJOI2008]树的统计Count

Time Limit: 10 Sec Memory Limit: 162 MB

Submit: 10559 Solved: 4258

[Submit][Status][Discuss]

Description

一棵树上有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本身

Input

输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。 对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。

Output

对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。

Sample Input

4

1 2

2 3

4 1

4 2 1 3

12

QMAX 3 4

QMAX 3 3

QMAX 3 2

QMAX 2 3

QSUM 3 4

QSUM 2 1

CHANGE 1 5

QMAX 3 4

CHANGE 3 6

QMAX 3 4

QMAX 2 4

QSUM 3 4

Sample Output

4

1

2

2

10

6

5

6

5

16

HINT

Source

树的分治

题目标解树的分治,写起来很难。。。而且我也不会。。。。

把树链剖,存储个点的信息。然后hash到线段树上。。。线段树维护区间最大和区间求和即可。。。

模板题,就照着模板来了。。。。我居然也开始压代码了。。(QaQ)

详情分析:http://blog.csdn.net/DaD3zZ/article/details/50628472

代码= =:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define inf 1000000000
struct data1{int l,r,sum,max;}t[120005];
struct data2{int next,go;}edge[60005];
int tree[30005],pre[30005],end[30005],son[30005],fa[30005],data[30005],num[30005],top[30005],deep[30005];
int n,x,y,cnt,tot,Q;
char opt[10];
int max(int a,int b){if (a>b) return a;return b;}
int min(int a,int b){if (a>b) return b;return a;}
void addedge(int u,int v){edge[++cnt].go=v;edge[cnt].next=end[u];end[u]=cnt;}
void dfs_1(int now,int f,int d)
{
deep[now]=d;fa[now]=f;num[now]=1;
for (int i=end[now]; i; i=edge[i].next)
{
int go=edge[i].go;if (go==f) continue;
dfs_1(go,now,d+1);num[now]+=num[go];
if (!son[now] || num[go]>num[son[now]]) son[now]=go;
}
}//链剖dfs_1
void dfs_2(int now,int number)
{
top[now]=number;tree[now]=++tot;
pre[tree[now]]=now;
if (!son[now]) return;
dfs_2(son[now],number);
for (int i=end[now]; i; i=edge[i].next)
{
int go=edge[i].go;
if (go!=son[now] && go!=fa[now]) dfs_2(go,go);
}
}//链剖dfs_2
void updata(int now)
{
t[now].sum=t[now<<1].sum+t[now<<1|1].sum;
t[now].max=max(t[now<<1].max,t[now<<1|1].max);
}//线段树。。
void build(int now,int l,int r)
{
t[now].l=l;t[now].r=r;
if (l==r) {t[now].sum=t[now].max=data[pre[l]];return;}
int mid=(l+r)>>1;
build(now<<1,l,mid);build(now<<1|1,mid+1,r);
updata(now);
}
void insert(int now,int loc,int add)
{
if (t[now].l==t[now].r)
{
t[now].sum+=add*(t[now].r-t[now].l+1);
t[now].max+=add;return;
}
int mid=(t[now].r+t[now].l)>>1;
if (loc<=mid) insert(now<<1,loc,add);else insert(now<<1|1,loc,add);
updata(now);
}
int query_sum(int now,int L,int R)
{
if (L<=t[now].l && R>=t[now].r) return t[now].sum;
int mid=(t[now].r+t[now].l)>>1;int ans=0;
if (L<=mid) ans+=query_sum(now<<1,L,R);
if (mid<R) ans+=query_sum(now<<1|1,L,R);
updata(now);
return ans;
}
int query_max(int now,int L,int R)
{
if (L<=t[now].l && R>=t[now].r) return t[now].max;
int mid=(t[now].l+t[now].r)>>1;int ans=-inf;
if (L<=mid) ans=max(ans,query_max(now<<1,L,R));
if (mid<R) ans=max(ans,query_max(now<<1|1,L,R));
updata(now);
return ans;
}
int find_max(int x,int y)
{
int f1=top[x],f2=top[y],tmp,ans=-inf;
while (f1!=f2)
{
if (deep[f1]<deep[f2]) {tmp=f1;f1=f2;f2=tmp;tmp=x;x=y;y=tmp;}
ans=max(ans,query_max(1,tree[f1],tree[x]));
x=fa[f1];f1=top[x];
}
ans=max(ans,query_max(1,min(tree[x],tree[y]),max(tree[x],tree[y])));
return ans;
}//查询原树上信息的区间最大
int find_sum(int x,int y)
{
int f1=top[x],f2=top[y],tmp,ans=0;
while (f1!=f2)
{
if (deep[f1]<deep[f2]) {tmp=f1;f1=f2;f2=tmp;tmp=x;x=y;y=tmp;}
ans+=query_sum(1,tree[f1],tree[x]);
x=fa[f1];f1=top[x];
}
ans+=query_sum(1,min(tree[x],tree[y]),max(tree[x],tree[y]));
return ans;
}//查询原树上信息的区间和
int main()
{
scanf("%d",&n);
for (int i=1; i<=n-1; i++)
{
scanf("%d%d",&x,&y);
addedge(x,y);addedge(y,x);
}
for (int i=1; i<=n; i++)
scanf("%d",&data[i]);
dfs_1(1,0,1);dfs_2(1,1);
build(1,1,n);
scanf("%d",&Q);
while (Q)
{
Q--;
scanf("%s%d%d",&opt,&x,&y);
if (opt[0]=='C') insert(1,tree[x],y-data[x]),data[x]=y;
else if (opt[1]=='M') printf("%d\n",find_max(x,y));
else if (printf("%d\n",find_sum(x,y)));
}
return 0;
}

BZOJ-1036 树的统计Count 链剖线段树(模板)=(树链剖分+线段树)的更多相关文章

  1. 【BZOJ1036】[ZJOI2008] 树的统计Count(一道可怕的模板题:树剖+线段树)

    点此看题面 题解 这真的只是一道模板题:一个树链剖分套上一个线段树(令我窒息的组合). 既然是模板题,那就直接上代码吧. 代码 #include<bits/stdc++.h> #defin ...

  2. BZOJ 1036: [ZJOI2008]树的统计Count [树链剖分]【学习笔记】

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 14302  Solved: 5779[Submit ...

  3. Bzoj 1036: [ZJOI2008]树的统计Count 树链剖分,LCT

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 11102  Solved: 4490[Submit ...

  4. BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)

    BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...

  5. bzoj 1036 [ZJOI2008]树的统计Count(树链剖分,线段树)

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 10677  Solved: 4313[Submit ...

  6. BZOJ 1036: [ZJOI2008]树的统计Count( 树链剖分 )

    树链剖分... 不知道为什么跑这么慢 = = 调了一节课啊跪.. ------------------------------------------------------------------- ...

  7. bzoj 1036: [ZJOI2008]树的统计Count 树链剖分+线段树

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 16294  Solved: 6645[Submit ...

  8. BZOJ 1036: [ZJOI2008]树的统计Count (树链剖分模板题)

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 14982  Solved: 6081[Submit ...

  9. bzoj 1036: [ZJOI2008]树的统计Count (树链剖分+线段树 点权)

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 21194  Solved: 8589[Submit ...

  10. BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分)(线段树单点修改)

    [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 14968  Solved: 6079[Submit][Stat ...

随机推荐

  1. Sprite Editor 图集切片精灵

    切图需求 假设有一张大的UI的图集,我们想把它里面的小图一张一张地切割出来,如果有plist文件,请查阅我的另一篇文章<还原TexturePacker plist 文件 切开各小图片> 今 ...

  2. 监控Mysql主从环境下Slave延迟状态的操作记录

    在MySQL主从环境下,通常会根据Seconds_Behind_Master的值来判断slave的延迟状态,这么做在大部分情况下尚可接受,但其实是并不够准确的.对于Slave延迟状态的监控,应该考虑多 ...

  3. 哎呀,发现自己不会用模块的方式用kprobe啊,弱爆了

    在内核外面编译模块,会报warning函数名undefined的错误,解决方法是把函数给export出来:EXPORT_SYMBOL 一直以来,用kprobe比较多的是kprobe event的用法, ...

  4. jQuery Mobile和Sencha Touch哪个更适合你?

    纯粹的总结一下移动web开发框架,移动web开发框架有jQuery Mobile .Sencha Touch等等,他们都来源于web开发,是成熟的框架,jQuery Mobile出自于jQuery家族 ...

  5. 神奇的GO语言:空接口(interface)

    对于go语言来说,设计最精妙的应该是interface了,直白点说interface是一组method的组合.至于更加详细的描述,本文不做介绍,今天谈谈空接口. 空interface(interfac ...

  6. win PPTP场景与搭建

    远程访问方案: 1,端口映射 2,vpn   实现这种远程访问的协议:pptp 等.     场景: 要从考试服务器[电信]下载题目. 单位有两个办事处,A双出口,B单网通出口. B要下载题,很慢. ...

  7. [转]World Wind Java开发之四——搭建本地WMS服务器

    在提供地理信息系统客户端时,NASA还为用户提供了开源的WMS Server 服务器应用:World Wind WMS Server.利用这个应用,我们可以架设自己的WMS服务并使用自己的数据(也支持 ...

  8. MySQL基础 - 内置函数

    Concat() 用于连接字段,一般DBMS使用+或者||. ex: 注意:上图中新检索出来的列名为'CONCAT(id, '->', name)'(实际上没有列名),这样虽然不影响在MySQL ...

  9. HTML语义化之常见模块

    用合理的HTML标记以及特有的属性去格式化文档内容. 浏览器会根据标签的语义给定一个默认的样式. 判断网页标签语义是否良好的一个简单方法就是:去掉样式,看网页结构是否组织良好有序,是否仍然有很好的可读 ...

  10. OC格式化标准符

    %@       对象     •    %d, %i   整数     •    %u        无符整形     •    %f         浮点/双字     •    %x, %X   ...