【刷题】BZOJ 1036 [ZJOI2008]树的统计Count
Description
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成
一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I
II. 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
Solution
这题还是很水的
只要维护链上的信息,又是静态,没有加删边
所以LCT和树剖都可以做
这是LCT的代码:(自带大常数)
#include<bits/stdc++.h>
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
const int MAXN=30000+10,inf=0x3f3f3f3f;
int n,q;
#define lc(x) ch[(x)][0]
#define rc(x) ch[(x)][1]
struct LCT{
int ch[MAXN][2],fa[MAXN],rev[MAXN],val[MAXN],Mx[MAXN],Sm[MAXN],stack[MAXN],cnt;
inline void init()
{
memset(Mx,-inf,sizeof(Mx));
memset(val,-inf,sizeof(val));
}
inline bool nroot(int x)
{
return lc(fa[x])==x||rc(fa[x])==x;
}
inline void reverse(int x)
{
std::swap(lc(x),rc(x));
rev[x]^=1;
}
inline void pushup(int x)
{
Sm[x]=(val[x]!=-inf?val[x]:0)+Sm[lc(x)]+Sm[rc(x)];
Mx[x]=val[x];
if(Mx[lc(x)]>Mx[x])Mx[x]=Mx[lc(x)];
if(Mx[rc(x)]>Mx[x])Mx[x]=Mx[rc(x)];
}
inline void pushdown(int x)
{
if(rev[x])
{
if(lc(x))reverse(lc(x));
if(rc(x))reverse(rc(x));
rev[x]=0;
}
}
inline void rotate(int x)
{
int f=fa[x],p=fa[f],c=(rc(f)==x);
if(nroot(f))ch[p][rc(p)==f]=x;
fa[ch[f][c]=ch[x][c^1]]=f;
fa[ch[x][c^1]=f]=x;
fa[x]=p;
pushup(f);
pushup(x);
}
inline void splay(int x)
{
cnt=0;
stack[++cnt]=x;
for(register int i=x;nroot(i);i=fa[i])stack[++cnt]=fa[i];
while(cnt)pushdown(stack[cnt--]);
for(register int y=fa[x];nroot(x);rotate(x),y=fa[x])
if(nroot(y))rotate((lc(y)==x)==(lc(fa[y])==y)?y:x);
pushup(x);
}
inline void access(int x)
{
for(register int y=0;x;x=fa[y=x])splay(x),rc(x)=y,pushup(x);
}
inline void makeroot(int x)
{
access(x);splay(x);reverse(x);
}
inline void split(int x,int y)
{
makeroot(x);access(y);splay(y);
}
inline void link(int x,int y)
{
makeroot(x);fa[x]=y;
}
};
LCT T;
#undef lc
#undef rc
template<typename T> inline void read(T &x)
{
T data=0,w=1;
char ch=0;
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
x=data*w;
}
template<typename T> inline void write(T x,char c='\0')
{
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
if(c!='\0')putchar(c);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
int main()
{
read(n);
T.init();
for(register int i=1;i<n;++i)
{
int u,v;
read(u);read(v);
T.link(u,v);
}
for(register int i=1;i<=n;++i)T.access(i),T.splay(i),read(T.val[i]),T.pushup(i);
read(q);
while(q--)
{
char opt[8];int u,v;
scanf("%s",opt);read(u);read(v);
if(!strcmp(opt,"QMAX"))T.split(u,v),write(T.Mx[v],'\n');
if(!strcmp(opt,"QSUM"))T.split(u,v),write(T.Sm[v],'\n');
if(!strcmp(opt,"CHANGE"))T.access(u),T.splay(u),T.val[u]=v,T.pushup(u);
}
return 0;
}
这是树剖的代码(老代码,以前的):
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define Mid ((l+r)>>1)
#define lson rt<<1,l,Mid
#define rson rt<<1|1,Mid+1,r
const ll MAXN=30000+10;
ll n,m,Mod,to[MAXN<<1],nex[MAXN<<1],beg[MAXN],fa[MAXN],Tre[MAXN],Val[MAXN],size[MAXN],Sum[MAXN<<2],Add[MAXN<<2],sta[MAXN],end[MAXN],hson[MAXN],cnt,e,dep[MAXN],top[MAXN],Max[MAXN<<2];
inline void read(ll &x)
{
ll data=0,w=1;
char ch=0;
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch>='0'&&ch<='9')data=(data<<3)+(data<<1)+(ch^'0'),ch=getchar();
x=data*w;
}
inline void insert(ll x,ll y)
{
to[++e]=y;
nex[e]=beg[x];
beg[x]=e;
}
inline void dfs1(ll x,ll f)
{
ll tmp=0;
fa[x]=f;
size[x]=1;
dep[x]=dep[f]+1;
for(register ll i=beg[x];i;i=nex[i])
if(to[i]==f)continue;
else
{
dfs1(to[i],x);
size[x]+=size[to[i]];
if(size[to[i]]>tmp)tmp=size[to[i]],hson[x]=to[i];
}
}
inline void dfs2(ll x,ll head)
{
top[x]=head;
sta[x]=++cnt;
Val[cnt]=Tre[x];
if(hson[x])dfs2(hson[x],head);
for(register ll i=beg[x];i;i=nex[i])
if(to[i]==fa[x]||to[i]==hson[x])continue;
else dfs2(to[i],to[i]);
end[x]=cnt;
}
inline void PushUp(ll rt)
{
Sum[rt]=Sum[rt<<1]+Sum[rt<<1|1];
Max[rt]=max(Max[rt<<1],Max[rt<<1|1]);
}
inline void PushDown(ll rt,ll len)
{
Add[rt<<1]+=Add[rt];
Add[rt<<1|1]+=Add[rt];
Max[rt<<1]+=Add[rt];
Max[rt<<1|1]+=Add[rt];
Sum[rt<<1]+=Add[rt]*(len-(len>>1));
Sum[rt<<1|1]+=Add[rt]*(len>>1);
Add[rt]=0;
}
inline void Build(ll rt,ll l,ll r)
{
if(l==r)Sum[rt]=Val[l],Max[rt]=Val[l];
else
{
Build(lson);
Build(rson);
PushUp(rt);
}
}
inline void init()
{
dfs1(1,0);
dfs2(1,1);
Build(1,1,n);
}
inline void Update(ll rt,ll l,ll r,ll pos,ll k)
{
if(l==r&&r==pos)
{
Max[rt]=k;
Sum[rt]=k;
}
else
{
if(Add[rt])PushDown(rt,r-l+1);
if(pos<=Mid)Update(lson,pos,k);
else if(pos>Mid)Update(rson,pos,k);
PushUp(rt);
}
}
inline ll Query(ll rt,ll l,ll r,ll L,ll R)
{
if(L<=l&&r<=R)return Sum[rt];
else
{
if(Add[rt])PushDown(rt,r-l+1);
ll tmp=0;
if(L<=Mid)tmp+=Query(lson,L,R);
if(R>Mid)tmp+=Query(rson,L,R);
return tmp;
}
}
inline ll Maxfind(ll rt,ll l,ll r,ll L,ll R)
{
if(L<=l&&r<=R)return Max[rt];
else
{
if(Add[rt])PushDown(rt,r-l+1);
ll tmp=-1e18;
if(L<=Mid)tmp=max(tmp,Maxfind(lson,L,R));
if(R>Mid)tmp=max(tmp,Maxfind(rson,L,R));
return tmp;
}
}
inline ll Getmax(ll x,ll y)
{
ll res=-1e18;
while(top[x]!=top[y])
if(dep[top[x]]>dep[top[y]])
{
res=max(Maxfind(1,1,n,sta[top[x]],sta[x]),res);
x=fa[top[x]];
}
else
{
res=max(Maxfind(1,1,n,sta[top[y]],sta[y]),res);
y=fa[top[y]];
}
res=max(res,Maxfind(1,1,n,min(sta[x],sta[y]),max(sta[x],sta[y])));
return res;
}
inline ll Getans(ll x,ll y)
{
ll res=0;
while(top[x]!=top[y])
if(dep[top[x]]>dep[top[y]])
{
res+=Query(1,1,n,sta[top[x]],sta[x]);
x=fa[top[x]];
}
else
{
res+=Query(1,1,n,sta[top[y]],sta[y]);
y=fa[top[y]];
}
res+=Query(1,1,n,min(sta[x],sta[y]),max(sta[x],sta[y]));
return res;
}
int main()
{
read(n);
for(register ll i=1;i<n;++i)
{
ll u,v;
read(u);read(v);
insert(u,v);insert(v,u);
}
for(register ll i=1;i<=n;++i)read(Tre[i]);
init();
read(m);
while(m--)
{
char str[10];
scanf("%s",str);
if(!strcmp(str,"QMAX"))
{
ll x,y;
read(x);read(y);
printf("%lld\n",Getmax(x,y));
}
else if(!strcmp(str,"QSUM"))
{
ll x,y;
read(x);read(y);
printf("%lld\n",Getans(x,y));
}
else if(!strcmp(str,"CHANGE"))
{
ll x,t;
read(x);read(t);
Update(1,1,n,sta[x],t);
}
}
return 0;
}
【刷题】BZOJ 1036 [ZJOI2008]树的统计Count的更多相关文章
- BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)
BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...
- BZOJ 1036: [ZJOI2008]树的统计Count (树链剖分模板题)
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 14982 Solved: 6081[Submit ...
- Bzoj 1036: [ZJOI2008]树的统计Count 树链剖分,LCT
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 11102 Solved: 4490[Submit ...
- 数据结构(LCT动态树):BZOJ 1036: [ZJOI2008]树的统计Count
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 12266 Solved: 4945[Submit ...
- bzoj 1036: [ZJOI2008]树的统计Count 树链剖分+线段树
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 16294 Solved: 6645[Submit ...
- BZOJ 1036: [ZJOI2008]树的统计Count [树链剖分]【学习笔记】
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 14302 Solved: 5779[Submit ...
- BZOJ 1036: [ZJOI2008]树的统计Count
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MB Submit: 14354 Solved: 5802 [Subm ...
- bzoj 1036 [ZJOI2008]树的统计Count(树链剖分,线段树)
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 10677 Solved: 4313[Submit ...
- BZOJ 1036: [ZJOI2008]树的统计Count( 树链剖分 )
树链剖分... 不知道为什么跑这么慢 = = 调了一节课啊跪.. ------------------------------------------------------------------- ...
- bzoj 1036: [ZJOI2008]树的统计Count (树链剖分+线段树 点权)
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 21194 Solved: 8589[Submit ...
随机推荐
- Apache入门篇(一)之安装部署apache
一.HTTPD特性 (1)高度模块化:core(核心) + modules(模块) = apache(2)动态模块加载DSO机制: Dynamic Shared Object(动态共享对象)(3)MP ...
- weka使用笔记3---classfily API调用
分类器在数据挖掘中的作用不言而喻,weka中的分类器有很多种类型,但是weka在输出结果中,只输出了一个分类的预测的类型,没有输出分类的得分,有一些不给力.如果想知道得分和其预测的类的话,就得调用we ...
- Yii2 使用 bootboxJS美化confirm窗口
有些关键操作比如删除,我们在执行前一般先弹出来个confirm确认窗口. 在Yii2中为一个操作添加confirm确认很容易.只需在链接出添加一个‘data-confirm' => '确实要添加 ...
- cogs1341 永无乡
cogs1341 永无乡 打了一发替罪羊树. 鬼故事:替罪羊树去掉重构(变成裸的二叉排序树)依然跑得过= = 启发式合并.每次把小的里面所有东西往大的里面一丢,每个点最多被丢\(log_2n\)次(丢 ...
- 八、Django之Models(译)
模型(Models) 模型是你的数据的唯一的.确定的信息源. 它包含你所储存数据的必要字段和行为. 通常,每个模型对应数据库中唯一的一张表. 基础: 每个模型都是一个Python类,它们都是djang ...
- Redis主从复制(Master/Slave) 与哨兵模式
Redis主从复制是什么? 行话:也就是我们所说的主从复制,主机数据更新后根据配置和策略, 自动同步到备机的master/slaver机制,Master以写为主,Slave以读为主 Redis主从复制 ...
- 「Leetcode」976. Largest Perimeter Triangle(C++)
分析 好久不刷题真的思维僵化,要考虑到这样一个结论:如果递增的三个数\(x_i,x_{i+1},x_{i+2}\)不符合题意,那么最大的两边之差一定大于等于第一条边,那么任何比第一条边小的都不能成立. ...
- Sublime Text3.0的安装
Sublime Text是一款轻量级的易于使用的前端编写软件,个人比较推荐. 找到Sublime的官网,下载对应的版本后,点击安装.安装完成后需要下载相应的插件才能进行更加 有效率的开发工作.编写前端 ...
- 韦大仙--LoadRunner压力测试:详细操作流程
一. 录制脚本 1.安装完毕后,创建脚本: 点击OK之后,会弹出网址,之后创建Action,每进一个页面添加一个Action,录制结束后,终止录制. 二. 修改脚本 1.脚本参数化 将登录的用户名密码 ...
- 数据库sql优化总结之1-百万级数据库优化方案+案例分析
项目背景 有三张百万级数据表 知识点表(ex_subject_point)9,316条数据 试题表(ex_question_junior)2,159,519条数据 有45个字段 知识点试题关系表(ex ...