题目:http://cojs.tk/cogs/problem/problem.php?pid=1583

1583. [POJ3237]树的维护

★★★☆   输入文件:maintaintree.in   输出文件:maintaintree.out   简单对比
时间限制:5 s   内存限制:128 MB

【题目描述】

给你由N个结点组成的树。树的节点被编号为1到N,边被编号为1到N-1。每一条边有一个权值。然后你要在树上执行一系列指令。指令可以是如下三种之一:

CHANGE i v:将第i条边的权值改成v。

NEGATE a b:将点a到点b路径上所有边的权值变成其相反数。

QUERY a b:找出点a到点b路径上各边的最大权值。

【输入格式】

输入文件的第一行有一个整数N(N<=10000)。

接下来N-1行每行有三个整数a,b,c,代表点a和点b之间有一条权值为c的边。这些边按照其编号从小到大给出。

接下来是若干条指令(不超过10^5条),都按照上面所说的格式。

输入文件的最后一行是"DONE".

【输出格式】

对每个“QUERY”指令,输出一行,即路径上各边的最大权值。

【样例输入】

3

1 2 1

2 3 2

QUERY 1 2

CHANGE 1 3

QUERY 1 2

DONE

【样例输出】

1

3

【提示】

这里的输入输出格式和POJ上原题略有不同。

【来源】

POJ 3237 Tree

题解:

LCT维护一下最大值和最小值,当要变为相反数时,把 最大值变为原来的最小值的相反数,最小值变为原来最大值的相反数 即可。。。

 #include<bits/stdc++.h>
using namespace std;
#define INF 1e9
#define MAXN 10010
struct node
{
int left,right,mx,mn,val;
}tree[*MAXN];
int rev[*MAXN],tag[*MAXN],father[*MAXN],Stack[*MAXN],n;
int read()
{
int s=,fh=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')fh=-;ch=getchar();}
while(ch>=''&&ch<=''){s=s*+(ch-'');ch=getchar();}
return s*fh;
}
int isroot(int x)
{
return tree[father[x]].left!=x&&tree[father[x]].right!=x;
}
void pushdown(int x)
{
int l=tree[x].left,r=tree[x].right;
if(rev[x]!=)
{
rev[x]^=;rev[l]^=;rev[r]^=;
swap(tree[x].left,tree[x].right);
}
if(tag[x]!=)
{
tag[x]^=;tag[l]^=;tag[r]^=;
tree[l].val=-tree[l].val;
tree[r].val=-tree[r].val;
swap(tree[l].mx,tree[l].mn);
tree[l].mx=-tree[l].mx;tree[l].mn=-tree[l].mn;
swap(tree[r].mx,tree[r].mn);
tree[r].mx=-tree[r].mx;tree[r].mn=-tree[r].mn;
}
}
void pushup(int x)
{
int l=tree[x].left,r=tree[x].right;
tree[x].mx=max(tree[l].mx,tree[r].mx);
if(x>n)tree[x].mx=max(tree[x].mx,tree[x].val);
tree[x].mn=min(tree[l].mn,tree[r].mn);
if(x>n)tree[x].mn=min(tree[x].mn,tree[x].val);
}
void rotate(int x)
{
int y=father[x],z=father[y];
if(!isroot(y))
{
if(tree[z].left==y)tree[z].left=x;
else tree[z].right=x;
}
if(tree[y].left==x)
{
father[x]=z;father[y]=x;tree[y].left=tree[x].right;tree[x].right=y;father[tree[y].left]=y;
}
else
{
father[x]=z;father[y]=x;tree[y].right=tree[x].left;tree[x].left=y;father[tree[y].right]=y;
}
pushup(y);pushup(x);
}
void splay(int x)
{
int top=,i,y,z;Stack[++top]=x;
for(i=x;!isroot(i);i=father[i])Stack[++top]=father[i];
for(i=top;i>=;i--)pushdown(Stack[i]);
while(!isroot(x))
{
y=father[x],z=father[y];
if(!isroot(y))
{
if((tree[y].left==x)^(tree[z].left==y))rotate(x);
else rotate(y);
}
rotate(x);
}
}
void access(int x)
{
int last=;
while(x!=)
{
splay(x);
tree[x].right=last;pushup(x);
last=x;x=father[x];
}
}
void makeroot(int x)
{
access(x);splay(x);rev[x]^=;
}
void link(int u,int v)
{
makeroot(u);father[u]=v;splay(u);
}
void cut(int u,int v)
{
makeroot(u);access(v);splay(v);father[u]=tree[v].left=;
}
int findroot(int x)
{
access(x);splay(x);
while(tree[x].left!=)x=tree[x].left;
return x;
}
int main()
{
freopen("maintaintree.in","r",stdin);
freopen("maintaintree.out","w",stdout);
int i,a,b,c;
char fh[];
n=read();
for(i=;i<=*n;i++)tree[i].mx=-INF,tree[i].mn=INF;
for(i=;i<n;i++)
{
a=read();b=read();c=read();
tree[n+i].mx=tree[n+i].mn=tree[n+i].val=c;
link(a,n+i);link(n+i,b);
}
while()
{
scanf("\n%s",fh);
if(fh[]=='D')break;
if(fh[]=='Q')
{
a=read();b=read();
makeroot(a);access(b);splay(b);
printf("%d\n",tree[b].mx);
}
else if(fh[]=='C')
{
a=read();b=read();
makeroot(n+a);tree[n+a].mn=tree[n+a].mx=tree[n+a].val=b;
}
else
{
a=read();b=read();
makeroot(a);access(b);splay(b);
tag[b]^=;
swap(tree[b].mx,tree[b].mn);
tree[b].val=-tree[b].val;
tree[b].mx=-tree[b].mx;
tree[b].mn=-tree[b].mn;
}
}
fclose(stdin);
fclose(stdout);
return ;
}

2016.3.24

补一发树链剖分:

 #include<bits/stdc++.h>
using namespace std;
#define MAXN 10010
#define INF 1e9
struct node
{
int begin,end,value,next;
}edge[*MAXN];
struct NODE
{
int left,right,mx,mn,tag;
}tree[*MAXN];
int cnt,Head[MAXN],n,size[MAXN],deep[MAXN],P[MAXN][],pos[MAXN],belong[MAXN],id[MAXN],vv[MAXN],U[MAXN],V[MAXN],VAL[MAXN],SIZE;
bool vis[MAXN];
void addedge(int bb,int ee,int vv)
{
edge[++cnt].begin=bb;edge[cnt].end=ee;edge[cnt].value=vv;edge[cnt].next=Head[bb];Head[bb]=cnt;
}
void addedge1(int bb,int ee,int vv)
{
addedge(bb,ee,vv);addedge(ee,bb,vv);
}
int read()
{
int s=,fh=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')fh=-;ch=getchar();}
while(ch>=''&&ch<=''){s=s*+(ch-'');ch=getchar();}
return s*fh;
}
void dfs1(int u)
{
int i,v;
size[u]=;vis[u]=true;
for(i=Head[u];i!=-;i=edge[i].next)
{
v=edge[i].end;
if(vis[v]==false)
{
deep[v]=deep[u]+;
P[v][]=u;
dfs1(v);
size[u]+=size[v];
}
}
}
void Ycl()
{
int i,j;
for(j=;(<<j)<=n;j++)
{
for(i=;i<=n;i++)
{
if(P[i][j-]!=-)P[i][j]=P[P[i][j-]][j-];
}
}
}
void dfs2(int u,int chain)
{
int k=,i,v;
pos[u]=++SIZE;belong[u]=chain;
for(i=Head[u];i!=-;i=edge[i].next)
{
v=edge[i].end;
if(deep[v]>deep[u]&&size[v]>size[k])k=v;
}
if(k==)return;
dfs2(k,chain);
for(i=Head[u];i!=-;i=edge[i].next)
{
v=edge[i].end;
if(deep[v]>deep[u]&&v!=k)dfs2(v,v);
}
}
int LCA(int x,int y)
{
int i,j;
if(deep[x]<deep[y])swap(x,y);
for(i=;(<<i)<=deep[x];i++);i--;
for(j=i;j>=;j--)if(deep[x]-(<<j)>=deep[y])x=P[x][j];
if(x==y)return x;
for(j=i;j>=;j--)
{
if(P[x][j]!=-&&P[x][j]!=P[y][j])
{
x=P[x][j];
y=P[y][j];
}
}
return P[x][];
}
void Pushup(int k)
{
tree[k].mx=max(tree[k*].mx,tree[k*+].mx);
tree[k].mn=min(tree[k*].mn,tree[k*+].mn);
}
void Pushdown(int k)
{
int l=k*,r=k*+;
if(tree[k].tag!=)
{
tree[k].tag^=;tree[l].tag^=;tree[r].tag^=;
swap(tree[l].mn,tree[l].mx);
tree[l].mn=-tree[l].mn;tree[l].mx=-tree[l].mx;
swap(tree[r].mn,tree[r].mx);
tree[r].mn=-tree[r].mn;tree[r].mx=-tree[r].mx;
}
}
void Build(int k,int l,int r)
{
tree[k].left=l;tree[k].right=r;tree[k].mx=-INF;tree[k].mn=INF;tree[k].tag=;
if(l==r)
{
tree[k].mx=tree[k].mn=vv[l];
return;
}
int mid=(l+r)/;
Build(k*,l,mid);Build(k*+,mid+,r);
Pushup(k);
}
void Change(int k,int lr,int C)
{
if(tree[k].left==tree[k].right){tree[k].mx=tree[k].mn=C;return;}
Pushdown(k);
int mid=(tree[k].left+tree[k].right)/;
if(lr<=mid)Change(k*,lr,C);
else Change(k*+,lr,C);
Pushup(k);
}
int Query_max(int k,int l,int r)
{
if(l<=tree[k].left&&tree[k].right<=r)return tree[k].mx;
Pushdown(k);
int mid=(tree[k].left+tree[k].right)/;
if(r<=mid)return Query_max(k*,l,r);
else if(l>mid)return Query_max(k*+,l,r);
else return max(Query_max(k*,l,mid),Query_max(k*+,mid+,r));
}
int Solve_max(int x,int f)
{
int MAX=-INF;
while(belong[x]!=belong[f])
{
MAX=max(MAX,Query_max(,pos[belong[x]],pos[x]));
x=P[belong[x]][];
}
if(x!=f)MAX=max(MAX,Query_max(,pos[f]+,pos[x]));
return MAX;
}
void Negate(int k,int l,int r)
{
if(l<=tree[k].left&&tree[k].right<=r/*tree[k].left==tree[k].right*/)
{
swap(tree[k].mn,tree[k].mx);
tree[k].mn=-tree[k].mn;tree[k].mx=-tree[k].mx;
tree[k].tag^=;
return;
}
Pushdown(k);
int mid=(tree[k].left+tree[k].right)/;
if(r<=mid)Negate(k*,l,r);
else if(l>mid)Negate(k*+,l,r);
else {Negate(k*,l,mid);Negate(k*+,mid+,r);}
Pushup(k);
}
void Solve_negate(int x,int f)
{
while(belong[x]!=belong[f])
{
Negate(,pos[belong[x]],pos[x]);
x=P[belong[x]][];
}
if(x!=f)Negate(,pos[f]+,pos[x]);
}
int main()
{
freopen("maintaintree.in","r",stdin);
freopen("maintaintree.out","w",stdout);
int i,I,W,bb,ee,lca;
char fh[];
n=read();
memset(Head,-,sizeof(Head));cnt=;
for(i=;i<n;i++)
{
U[i]=read();V[i]=read();VAL[i]=read();
addedge1(U[i],V[i],VAL[i]);
}
memset(P,-,sizeof(P));SIZE=;
dfs1();Ycl();
dfs2(,);
for(i=;i<n;i++)
{
if(deep[U[i]]>deep[V[i]])id[i]=U[i];
else id[i]=V[i];
}
for(i=;i<n;i++)vv[pos[id[i]]]=VAL[i];
Build(,,n);
while()
{
scanf("\n%s",fh);
if(fh[]=='D')break;
if(fh[]=='C')
{
I=read();W=read();
Change(,pos[id[I]],W);
}
else if(fh[]=='Q')
{
bb=read();ee=read();
lca=LCA(bb,ee);
printf("%d\n",max(Solve_max(bb,lca),Solve_max(ee,lca)));
}
else
{
bb=read();ee=read();
lca=LCA(bb,ee);
Solve_negate(bb,lca);
Solve_negate(ee,lca);
}
}
fclose(stdin);
fclose(stdout);
return ;
}

Cogs 1583. [POJ3237]树的维护 LCT,树链剖分的更多相关文章

  1. COGS 1583. [POJ3237]树的维护

    二次联通门 : COGS 1583. [POJ3237]树的维护 /* COGS 1583. [POJ3237]树的维护 树链剖分 + 边权化点权 线段树 单点修改 + 区间取相反数 + 查询区间最大 ...

  2. (持续更新)虚树,KD-Tree,长链剖分,后缀数组,后缀自动机

    真的就是讲课两天,吸收一个月呢! \(1.\)虚树 \(2.\)KD-Tree \(3.\)长链剖分 \(4.\)后缀数组 后缀数组 \(5.\)后缀自动机 后缀自动机

  3. 7.28 NOI模拟赛 H2O 笛卡尔树 并查集 贪心 长链剖分

    LINK:H2O 这场比赛打的稀烂 爆蛋. 只会暴力.感觉暴力细节比较多不想写. 其实这道题的难点就在于 采取什么样的策略放海绵猫. 知道了这一点才能确定每次放完海绵猫后的答案. 暴力枚举是不行的.而 ...

  4. cogs 1583. [POJ 3237] 树的维护 树链剖分套线段树

    1583. [POJ 3237] 树的维护 ★★★★   输入文件:maintaintree.in   输出文件:maintaintree.out   简单对比时间限制:5 s   内存限制:128 ...

  5. cogs1583. [POJ3237]树的维护

    1583. [POJ3237]树的维护 http://www.cogs.pro/cogs/problem/problem.php?pid=1583 ★★★☆   输入文件:maintaintree.i ...

  6. Cogs 1672. [SPOJ375 QTREE]难存的情缘 LCT,树链剖分,填坑计划

    题目:http://cojs.tk/cogs/problem/problem.php?pid=1672 1672. [SPOJ375 QTREE]难存的情缘 ★★★☆   输入文件:qtree.in  ...

  7. Cogs 1688. [ZJOI2008]树的统计Count(树链剖分+线段树||LCT)

    [ZJOI2008]树的统计Count ★★★ 输入文件:bzoj_1036.in 输出文件:bzoj_1036.out 简单对比 时间限制:5 s 内存限制:162 MB [题目描述] 一棵树上有n ...

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

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

  9. [CodeVS2370] 小机房的树 (LCA, 树链剖分, LCT)

    Description 小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上.有一天,他们想爬到一个节点上去搞基,但是作为两只虫子,他们不想花 ...

随机推荐

  1. SqlServer中的merge操作,相当地风骚

    今天在一个存储过程中看见了merge这个关键字,第一个想法是,这个是配置管理中的概念吗,把相邻两次的更改合并到一起.后来在technet上搜索发现别有洞天,原来是另外一个sql关键字,t-sql的语法 ...

  2. Jenkins integration for AngularJS code coverage

    Install Jenkins plugins 'Cobertura' and 'HTML Publisher' 1. add Post-build Actions "Publish HTM ...

  3. 使用Reveal.app调试整个项目UI时间,增加LD指令 -Objc引起项目中多个静态库冲突问题

    今天接触到一个新的UI调试工具教程如下: iOS真机UI调试利器——Reveal 引入增加-ObjC -framework Reveal指令后,发现项目出现多重静态库冲突问题, 首先介绍一个指令: - ...

  4. vector预分配空间溢出

    vector 当一个vector预分配的存储空间用完之后,为维护其连续的对象数组,它必须在另外一个地方重新分配大块新的(更大的)存储空间,并把以前已有的对象拷贝到新的存储空间中去. // A clas ...

  5. [Lua]表驱动索引编程,form.lua

    form.interface local form = {_tag = 'form'} function form.build(tag, super) --[[ -- form to produce ...

  6. [jQuery] Cannot read property ‘msie’ of undefined错误的解决方法

    最近把一个项目的jQuery升级到最新版,发现有些页面报错Cannot read property ‘msie’ of undefined.上jQuery网站上搜了一下,原因是$.browser这个a ...

  7. asp.net取HTML控件值

    asp.net取HTML控件值所有html表单里面的值控件,提交后都是以键值 key=value&key=value&……这样的形式提交给后台. radio也一样,会将选中的radio ...

  8. 经典SQL练习题

    题目地址:http://blog.csdn.net/qaz13177_58_/article/details/5575711 1. 查询Student表中的所有记录的Sname.Ssex和Class列 ...

  9. __set($key,$values) 和__get($varName) 魔术方法设置读取私有属性

    __set($key,$val) 对类内私有属性赋值 作用:对私有属性的处理 当在类外对类内的私有属性赋值时会自动调用此函数 __get($varName) 读取类内私有属性 作用:虽然可以外部访问, ...

  10. C语言笔记(二维数组与数值指针)

    一.关于二维数组和二维数组区别 (1)一维数组在内存中是连续分布存储的,同样,二维数组也是在内存连续存储的.所以从内存的角度来分析,一维数组和二维数组其实没有本质区别. (2) 二维数组可以使用一维数 ...