题目: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. Error parsing XML: not well-formed (invalid token)

    从网络上或别的文件复制粘贴进来的代码有隐含格式,可将内容先粘贴进记事本清除格式,再复制粘贴进工程文件,即可解决此问题 注:1. 要使工程文件全选清空, 2. 若粘贴后刷新仍无效果,可手动输入

  2. RABBITMQ安装注意点

    关于 RABBITMQ的配置问题安装问题windows7 和window 10我都试了windows10安装和配置不要出现中文和空格,不然你日寒飞的心都有了ERLANG的安装也是Win7直接默认的路径 ...

  3. LIB库加载方法-引用百度百科

    LIB库加载方法,有三种,如下: 1.LIB文件直接加入到工程文件列表中 在VC中打开File View一页,选中工程名,单击鼠标右键,然后选中\"Add Files to Project\ ...

  4. oracle 权限管理

    系统权限 系统权限需要授予者有进行系统级活动的能力,如连接数据库,更改用户会话.建立表或建立用户等等.你可以在数据字典视图SYSTEM_PRIVILEGE_MAP上获得完整的系统权限.对象权限和系统权 ...

  5. C#有关 字符串方法的使用

    using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Cons ...

  6. 对装饰模式(Decorator)的解读

    看过好多对装饰模式的讲解,他们几乎都有一句相同的话:对现有类功能的扩展.不知道大家怎么理解这句话的,之前我把”对功能的扩展“理解成”加功能=加方法“,比如Person类本来有两个功能:Eat 和 Ru ...

  7. jQuery 获取父元素、子元素、同级元素

    详情:http://www.w3school.com.cn/jquery/jquery_traversing_ancestors.asp   parent() 方法返回被选元素的直接父元素.(常用) ...

  8. coder

    #include <iostream>#include <GL/glut.h>using std::cout;using std::endl;float windowWidth ...

  9. VPN ,Bypass the FIrewall

    Bypass the China Firewall Methods November 16th, 2012Posted in , Tech With their assortment of techn ...

  10. [python]获取字符串类型

    >>>type(value) <class 'type'> >>>isinstance(value,type) True/False