http://poj.org/problem?id=3237 (题目链接)

树链剖分模板题,然而这150+行的程序我调了一天,历经艰辛,终于ac。。

题意

  给出一个n个节点的带权树,要求维护操作:1.求出树上两点之间的边权的最大值;2.更改一条边上的权值;3.将树上两点之间的所有边权取各自的相反数。

solution

  神奇的树链剖分+线段树维护查询和修改操作。

  树链剖分时,我们将每条边的权值转换为除树根外每个节点上的权值(也就是对于每个节点与它父亲的边的权值转换到了自己的权值)。

  之后就是标准的树链剖分后跑线段树了,那个全部取相反数的操作其实是一样的,树链剖分相关知识请见http://blog.sina.com.cn/s/blog_7a1746820100wp67.html

  编程时请注意细节,邻接表写错了就悲剧了。。

data

#include <ctime>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; int main() {
int i,j,k;
freopen("aaa.in","r",stdin);freopen("aaa.in","w",stdout);
puts("1");
srand((unsigned)time(NULL));
int n=rand()%1000+5;
printf("%d\n",n);
for(i=1;i<n;i++)
printf("%d %d %d\n",i+1,rand()%i+1,rand()%14513546);
for(i=1;i<n;i++) {
int opt=rand()%3;
if(opt==0)
printf("CHANGE %d %d\n",rand()%(n-1)+1,rand()%42534567);
else if(opt==1) {
int a=0,b=0;
while(a==b)a=rand()%n+1,b=rand()%n+1;
printf("NEGATE %d %d\n",a,b);
}
else {
int a=0,b=0;
while(a==b)a=rand()%n+1,b=rand()%n+1;
printf("QUERY %d %d\n",a,b);
}
}
puts("DONE");
fclose(stdin);fclose(stdout);
return 0;
}

代码

// poj3237
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#define MOD 1000000007
#define inf 2147483640
#define LL long long
#define free(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout);
using namespace std;
inline int getint() {
int x=0,f=1;char ch=getchar();
while (ch>'9' || ch<'0') {if (ch=='-') f=-1;ch=getchar();}
while (ch>='0' && ch<='9') {x=x*10+ch-'0';ch=getchar();}
return x*f;
} const int maxn=100010;
struct edge {int to,next,w;}e[maxn<<2];
struct tree {int l,r,tag,mn,mx;}tr[maxn<<2]; int pos[maxn],deep[maxn],head[maxn],bin[20],fa[maxn][20],size[maxn],to[maxn],bl[maxn];
int cnt,P,n; void insert(int u,int v,int w) {
e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;e[cnt].w=w;
e[++cnt].to=u;e[cnt].next=head[v];head[v]=cnt;e[cnt].w=w;
}
void solve(int &x,int &y) {
int t=x;x=-y;y=-t;
}
void update(int k)
{
tr[k].mn=min(tr[k<<1].mn,tr[k<<1|1].mn);
tr[k].mx=max(tr[k<<1].mx,tr[k<<1|1].mx);
}
void pushdown(int k) {
int l=tr[k].l,r=tr[k].r;
if (l==r || !tr[k].tag) return;
tr[k].tag=0;
tr[k<<1].tag^=1,tr[k<<1|1].tag^=1;
solve(tr[k<<1].mn,tr[k<<1].mx);
solve(tr[k<<1|1].mn,tr[k<<1|1].mx);
}
void build(int k,int s,int t) {
tr[k].l=s,tr[k].r=t,tr[k].tag=0,tr[k].mn=inf,tr[k].mx=-inf;
if (s==t) return;
int mid=(s+t)>>1;
build(k<<1,s,mid);
build(k<<1|1,mid+1,t);
}
void change(int k,int x,int val) {
pushdown(k);
int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
if (l==r) {tr[k].mn=tr[k].mx=val;return;}
if (x<=mid) change(k<<1,x,val);
else change(k<<1|1,x,val);
update(k);
}
void rever(int k,int x,int y) {
pushdown(k);
int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
if (l==x && r==y) {solve(tr[k].mn,tr[k].mx);tr[k].tag=1;return;}
if (y<=mid) rever(k<<1,x,y);
else if (x>mid) rever(k<<1|1,x,y);
else rever(k<<1,x,mid),rever(k<<1|1,mid+1,y);
update(k);
}
int query(int k,int x,int y) {
pushdown(k);
int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
if (l==x && r==y) return tr[k].mx;
if (y<=mid) return query(k<<1,x,y);
else if (x>mid) return query(k<<1|1,x,y);
else return max(query(k<<1,x,mid),query(k<<1|1,mid+1,y));
}
void dfs1(int x) {
size[x]=1;
for (int i=1;i<=13;i++) {
if (bin[i]<=deep[x]) fa[x][i]=fa[fa[x][i-1]][i-1];
else break;
}
for (int i=head[x];i;i=e[i].next) if (e[i].to!=fa[x][0]) {
deep[e[i].to]=deep[x]+1;
fa[e[i].to][0]=x;
dfs1(e[i].to);
size[x]+=size[e[i].to];
}
}
void dfs2(int x,int chain) {
/*
if (x==22) {
++P;
--P;
}
*/
bl[x]=chain;
pos[x]=++P;
int k=0;
for (int i=head[x];i;i=e[i].next) {
if (e[i].to!=fa[x][0]) {
if (size[e[i].to]>size[k]) k=e[i].to;
}
else {
to[i>>1]=pos[x];//记录每个节点在线段树上的标号
change(1,pos[x],e[i].w);//将权值插入线段树
}
}
if (!k) return;
dfs2(k,chain);
for (int i=head[x];i;i=e[i].next)
if (e[i].to!=fa[x][0] && e[i].to!=k) dfs2(e[i].to,e[i].to);
}
int lca(int x,int y) {
if (deep[x]<deep[y]) swap(x,y);
int t=deep[x]-deep[y];
for (int i=0;i<=13;i++) if (t&bin[i]) x=fa[x][i];
for (int i=13;i>=0;i--)
if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
if (x==y) return x;
return fa[x][0];
}
int solvequery(int x,int f) {
int mx=-inf;
while (bl[x]!=bl[f]) {
mx=max(mx,query(1,pos[bl[x]],pos[x]));
x=fa[bl[x]][0];
}
if (pos[f]+1<=pos[x]) mx=max(mx,query(1,pos[f]+1,pos[x]));
return mx;
}
void solverever(int x,int f) {
while (bl[x]!=bl[f]) {
rever(1,pos[bl[x]],pos[x]);
x=fa[bl[x]][0];
}
if (pos[f]+1<=pos[x]) rever(1,pos[f]+1,pos[x]);
}
int main() {
free("aaa");
int T=getint();
bin[0]=1;for (int i=1;i<15;i++) bin[i]=bin[i-1]<<1;
while (T--) {
P=0,cnt=1;//便于将边权转为点权
memset(head,0,sizeof(head));
memset(deep,0,sizeof(deep));
memset(fa,0,sizeof(fa));
n=getint();
for (int i=1;i<n;i++) {
int u=getint(),v=getint(),w=getint();
insert(u,v,w);
}
build(1,1,n);
dfs1(1);
dfs2(1,1);
char ch[10];
while (scanf("%s",ch+1)) {
if (ch[1]=='D') break;
int x=getint(),y=getint();
if (ch[1]=='Q') {
int f=lca(x,y);
printf("%d\n",max(solvequery(x,f),solvequery(y,f)));
}
if (ch[1]=='C') change(1,to[x],y);
if (ch[1]=='N') {
int f=lca(x,y);
solverever(x,f);solverever(y,f);
}
}
}
fclose(stdin);fclose(stdout);
return 0;
}

  

【poj3237】 Tree的更多相关文章

  1. 【POJ3237】Tree 树链剖分+线段树

    [POJ3237]Tree Description You are given a tree with N nodes. The tree's nodes are numbered 1 through ...

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

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

  3. 【POJ3237】Tree(树链剖分)

    题意:在一棵N个节点,有边权的树上维护以下操作: 1:单边修改,将第X条边的边权修改成Y 2:区间取反,将点X与Y在树上路径中的所有边边权取反 3:区间询问最大值,询问X到Y树上路径中边权最大值 n& ...

  4. 【BZOJ】【2631】Tree

    LCT 又一道名字叫做Tree的题目…… 看到删边加边什么的……又是动态树问题……果断再次搬出LCT. 这题比起上道[3282]tree的难点在于需要像线段树维护区间那样,进行树上路径的权值修改&am ...

  5. 【Luogu1501】Tree(Link-Cut Tree)

    [Luogu1501]Tree(Link-Cut Tree) 题面 洛谷 题解 \(LCT\)版子题 看到了顺手敲一下而已 注意一下,别乘爆了 #include<iostream> #in ...

  6. 【BZOJ3282】Tree (Link-Cut Tree)

    [BZOJ3282]Tree (Link-Cut Tree) 题面 BZOJ权限题呀,良心luogu上有 题解 Link-Cut Tree班子提 最近因为NOIP考炸了 学科也炸了 时间显然没有 以后 ...

  7. 【AtCoder3611】Tree MST(点分治,最小生成树)

    [AtCoder3611]Tree MST(点分治,最小生成树) 题面 AtCoder 洛谷 给定一棵\(n\)个节点的树,现有有一张完全图,两点\(x,y\)之间的边长为\(w[x]+w[y]+di ...

  8. 【HDU5909】Tree Cutting(FWT)

    [HDU5909]Tree Cutting(FWT) 题面 vjudge 题目大意: 给你一棵\(n\)个节点的树,每个节点都有一个小于\(m\)的权值 定义一棵子树的权值为所有节点的异或和,问权值为 ...

  9. 【BZOJ2654】Tree(凸优化,最小生成树)

    [BZOJ2654]Tree(凸优化,最小生成树) 题面 BZOJ 洛谷 题解 这道题目是之前\(Apio\)的时候写的,忽然发现自己忘记发博客了... 这个万一就是一个凸优化, 给所有白边二分一个额 ...

随机推荐

  1. 【转】【MySql】Waiting for table metadata lock原因分析

    MySQL在进行alter table等DDL操作时,有时会出现Waiting for table metadata lock的等待场景.而且,一旦alter table TableA的操作停滞在Wa ...

  2. Kafka及 .NET Core 客户端

    消息队列 Kafka 的基本知识及 .NET Core 客户端 消息队列 Kafka 的基本知识及 .NET Core 客户端   前言 最新项目中要用到消息队列来做消息的传输,之所以选着 Kafka ...

  3. Cannot resolve external dependency com.android.support:multidex:1.0.0

    multiDexEnabled true 去掉这一行,就OK了,是没有多dex支持么,但是又提供了这个

  4. codevs2806 红与黑

    难度等级:白银 codevs2806 红与黑 题目描述 Description 有一个矩形房间,覆盖正方形瓷砖.每块瓷砖涂成了红色或黑色.一名男子站在黑色的瓷砖上,由此出发,可以移到四个相邻瓷砖之一, ...

  5. Incorrect string value异常解决

    mysql数据库的一个问题 1366-Incorrect string value:'\xE5\x8D\xA1\xE5......' for column 'filename' at row 1 问题 ...

  6. mvc5 Html.EditorFor html属性有了新变化,和以前的不同了

    @Html.EditorFor(model => model.MaxNumber, new { htmlAttributes = new { @min = "1" } })

  7. href的那些事

    很多网站中都会使用<a>标签和 href属性来做链接,尤其在分页显示中用得最普遍.然而很多人对href的使用却并不十分了解. 1.href="#" 这个在网页中上滚回顶 ...

  8. Jquery和JS获取ul中li标签(转)

    js 获取元素下面所有的li var content=document.getElementById("content"); var items=content.getElemen ...

  9. HTML5+JS 《五子飞》游戏实现(二)路线分析和资源准备

    上一节 里沃特与我们分享了<五子飞>的下棋规则,可能有些伙伴看得不清楚,像我们码农还是看到代码比较靠谱.下面就把可以走棋的路线跟大家说一下. 假设从左上角开始,以0开始编号,往右数(没看第 ...

  10. 从Nodejs脚本到vue首页看开源始末的DemoHouse

    最近上Github看见了大漠的DemoHouse项目,看到Issues说准备做一个首页,于是我的第一想法就是做一个md列表页面,md文件可以很容易的生成一个html文件.刚刚做好脚本文件,可以生成li ...