数链剖分(Tree)
题目链接:https://cn.vjudge.net/contest/279350#problem/D
题目大意:操作,单点查询,区间取反,询问区间最大值。
AC代码:
#include<iostream>
#include<cmath>
#include<stack>
#include<queue>
#include<stdio.h>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
# define inf 0x3f3f3f3f
# define ll long long
# define lson l,m,rt<<
# define rson m+,r,rt<<|
const int maxn = 3e5+;
int sto[maxn],head[maxn],edgnum,dfsnum,depth[maxn];
int son[maxn],father[maxn],Size[maxn],ord[maxn],cost[maxn],top[maxn];
int maxtree[maxn<<],mintree[maxn<<],maxx,lazy[maxn<<];
struct node
{
int fr;
int to;
int nex;
int cost;
} edge[maxn],po[maxn];
void addedge(int fr,int to)
{
edge[edgnum].fr=fr;
edge[edgnum].to=to;
edge[edgnum].nex=head[fr];
head[fr]=edgnum++;
}
void dfs1(int fr,int rt,int dep)
{
father[fr]=rt;
Size[fr]=;
son[fr]=-;
depth[fr]=dep;
for(int i=head[fr]; i!=-; i=edge[i].nex)
{
int to=edge[i].to;
if(to==rt)
continue;
dfs1(to,fr,dep+);
Size[fr]+=Size[to];
if(son[to]==-||(Size[son[fr]]<Size[to]))
{
son[fr]=to;
}
}
}
void dfs2(int fr,int rt)
{
ord[fr]=++dfsnum;
cost[ord[fr]]=sto[fr];
top[fr]=rt;
if(son[fr]!=-)
dfs2(son[fr],rt);
for(int i=head[fr]; i!=-; i=edge[i].nex)
{
int u=edge[i].to;
if(son[fr]!=u&&father[fr]!=u)
{
dfs2(u,u);
}
}
}
void up(int rt)
{
maxtree[rt]=max(maxtree[rt<<],maxtree[rt<<|]);
mintree[rt]=min(mintree[rt<<],mintree[rt<<|]);
}
void buildtree(int l,int r,int rt)
{
if(l==r)
{
maxtree[rt]=sto[l];
mintree[rt]=sto[l];
lazy[rt]++;
return ;
}
int m=(l+r)>>;
buildtree(lson);
buildtree(rson);
up(rt);
}
void change(int rt)
{
int tmp=mintree[rt];
mintree[rt]=-maxtree[rt];
maxtree[rt]=-tmp;
}
void down(int rt)
{
if(!lazy[rt])
return ;
lazy[rt<<]^=;
lazy[rt<<|]^=;
change(rt<<);
change(rt<<|);
lazy[rt]^=;
}
void query(int l,int r,int rt,int L,int R)
{
if(L<=l&&R>=r)
{
maxx=max(maxx,maxtree[rt]);
return ;
}
down(rt);
int m=(l+r)>>;
if(L<=m)
query(lson,L,R);
if(R>m)
query(rson,L,R);
up(rt);
}
void update1(int l,int r,int rt,int pos,int p)
{
if(l==r)
{
maxtree[rt]=p;
mintree[rt]=p;
return ;
}
down(rt);
int m=(l+r)>>;
if(pos<=m)
update1(lson,pos,p);
if(pos>m)
update1(rson,pos,p);
up(rt);
}
void update2(int l,int r,int rt,int L,int R)
{
if(L<=l&&R>=r)
{
change(rt);
lazy[rt]^=;
return ;
}
down(rt);
int m=(l+r)>>;
if(L<=m)
update2(lson,L,R);
if(R>m)
update2(rson,L,R);
up(rt);
}
void Query(int n,int x,int y)
{
maxx=-inf;
int tx=top[x],ty=top[y];
while(tx!=ty)
{
if(depth[tx]<depth[ty])
{
swap(tx,ty);
swap(x,y);
}
query(,n,,ord[tx],ord[x]);
x=father[tx],tx=top[x];
}
if(depth[x]<depth[y])
{
swap(x,y);
}
query(,n,,ord[y]+,ord[x]);
}
void Update(int n,int x,int y)
{
int tx=top[x],ty=top[y];
while(tx!=ty)
{
if(depth[tx]<depth[ty])
{
swap(tx,ty);
swap(x,y);
}
update2(,n,,ord[tx],ord[x]);
x=father[tx],tx=top[x];
}
if(depth[x]<depth[y])
{
swap(x,y);
}
update2(,n,,ord[y]+,ord[x]);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
dfsnum=edgnum=;
int n,q,s;
scanf("%d",&n);
int t1,t2,t3;
memset(maxtree,,sizeof(maxtree));
memset(mintree,,sizeof(mintree));
memset(lazy,,sizeof(lazy));
memset(head,-,sizeof(head));
for(int i=; i<=n-; i++)
{
scanf("%d %d %d",&t1,&t2,&t3);
addedge(t1,t2);
addedge(t2,t1);
po[i].fr=t1;
po[i].to=t2;
po[i].cost=t3;
}
dfs1(,-,);
dfs2(,);
for(int i=; i<=n-; i++)
{
t1=depth[po[i].fr];
t2=depth[po[i].to];
if(t1>t2)
{
swap(po[i].fr,po[i].to);
}
update1(,n,,ord[po[i].to],po[i].cost);
}
char str[];
while(~scanf("%s",str))
{
if(str[]=='D')
break;
else if(str[]=='Q')
{
scanf("%d %d",&t1,&t2);
Query(n,t1,t2);
printf("%d\n",maxx);
}
else if(str[]=='C')
{
scanf("%d %d",&t1,&t2);
update1(,n,,ord[po[t1].to],t2);
}
else if(str[]=='N')
{
scanf("%d %d",&t1,&t2);
Update(n,t1,t2);
}
}
}
return ;
}
数链剖分(Tree)的更多相关文章
- G - Game HDU - 5242 (数链剖分)
题目链接: G - Game HDU - 5242 题目大意:首先是T组测试样例,给出一颗以1节点为根的树,每个节点有各自的价值,有m次从根节点出发向下走到叶子节点的机会,每次会得到所有经过节点的权值 ...
- 线段树&数链剖分
傻逼线段树,傻逼数剖 线段树 定义: 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点. 使用线段树可以快速的查找某一个节点在若干条线段中出现 ...
- 数链剖分(Aragorn's Story )
题目链接:https://vjudge.net/contest/279350#problem/A 题目大意:n个点,m条边,然后q次询问,因为在树上,两个点能确定一条直线,我们可以对这条直线上的所有值 ...
- 数链剖分(Housewife Wind )
题目链接:https://vjudge.net/contest/279350#problem/B 题目大意:给你n,q,s.n指的是有n个点,q代表有q次询问,s代表的是起点.然后接下来会有n-1条 ...
- 数链剖分(树的统计Count )
题目链接:https://cn.vjudge.net/contest/279350#problem/C 具体思路:单点更新,区间查询,查询的时候有两种操作,查询区间最大值和区间和. 注意点:在查询的时 ...
- POJ 3237 Tree (树链剖分)
Tree Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 2825 Accepted: 769 Description ...
- 浅谈树链剖分(C++、算法、树结构)
关于数链剖分我在网上看到的有几个比较好的讲解,本篇主要是对AC代码的注释(感谢各位witer的提供) 这是讲解 http://www.cnblogs.com/kuangbin/archive/2013 ...
- 1036: [ZJOI2008]树的统计Count (树链剖分)
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3401 Solved: 1418[Submit] ...
- HDU 3966 Aragorn's Story (树链剖分+树状数组)
Aragorn's Story Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
随机推荐
- 《Linux内核分析》第三周学习报告
<Linux内核分析>第三周学习报告 ——构造一个简单的Linux系统MenuOS 姓名:王玮怡 学号:201351 ...
- jieba分词学习
具体项目在githut里面: 应用jieba库分词 1)利用jieba分词来统计词频: 对应文本为我们队伍的介绍:jianjie.txt: 项目名称:碎片 项目描述:制作一个网站,拾起日常碎片,记录生 ...
- C#简述(三)
详细请参考:http://www.runoob.com/csharp/csharp-string.html 1.C# 字符串(String) 在 C# 中,可以使用字符数组来表示字符串,但是,更常见的 ...
- [转帖]将改名贯彻到底,Xeon E3系列将改名为Xeon E
将改名贯彻到底,Xeon E3系列将改名为Xeon E 导读: E3 系列改名为 XEON E 系列entry 入门级的含义 E5 1XXX 序列改名为 XEON W 系列 workstatio ...
- Android DatePickerDialog和TimePickerDialog显示样式
可以用DatePickerDialog显示选取日期的对话框.可以设置显示的样式 1.通过构造方法设置显示样式. 可以通过DatePickerDialog(Context context, int th ...
- Qt开发之Hello Qt及学习小技巧
创建第一个Qt程序的简单流程 如果安装了andriod或ios的版本也会显示出来,这里只显示了桌面端的 一个项目文件代码结构如下: 如下图可直接编辑label里的文字内容: 运行结果:(快捷键ctrl ...
- C语言变长数组data[0]
1.前言 在刷题时遇到一个结构中包含char data[0],第一次见到时感觉很奇怪,数组的长度怎么可以为零呢?于是上网搜索一下这样的用法的目的,发现在linux内核中,结构体中经常用到data[0] ...
- developer roadmap
developer roadmap https://balsamiq.com/ https://balsamiq.com/givingback/free/ https://balsamiq.cloud ...
- shit aliyun
shit aliyun 垃圾的 aliyun 什么鬼逻辑,怎么填写都不对,holy shit! 校验规则: // 对不起,昵称包含不可接受字符或被管理员屏蔽,请选择其它昵称 // 昵称的长度必须大于等 ...
- Mysql学习实践---SELECT INTO的替代方案
从一个表复制数据,然后把数据插入到另一个新表中. 假设有一个已创建且有数据的orders表,要把orders表备份到还未创建的newOrders表里 SQL用法:SELECT * INTO newOr ...