题目: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维护一下最大值和最小值,当要变为相反数时,把 最大值变为原来的最小值的相反数,最小值变为原来最大值的相反数 即可。。。

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define INF 1e9
  4. #define MAXN 10010
  5. struct node
  6. {
  7. int left,right,mx,mn,val;
  8. }tree[*MAXN];
  9. int rev[*MAXN],tag[*MAXN],father[*MAXN],Stack[*MAXN],n;
  10. int read()
  11. {
  12. int s=,fh=;char ch=getchar();
  13. while(ch<''||ch>''){if(ch=='-')fh=-;ch=getchar();}
  14. while(ch>=''&&ch<=''){s=s*+(ch-'');ch=getchar();}
  15. return s*fh;
  16. }
  17. int isroot(int x)
  18. {
  19. return tree[father[x]].left!=x&&tree[father[x]].right!=x;
  20. }
  21. void pushdown(int x)
  22. {
  23. int l=tree[x].left,r=tree[x].right;
  24. if(rev[x]!=)
  25. {
  26. rev[x]^=;rev[l]^=;rev[r]^=;
  27. swap(tree[x].left,tree[x].right);
  28. }
  29. if(tag[x]!=)
  30. {
  31. tag[x]^=;tag[l]^=;tag[r]^=;
  32. tree[l].val=-tree[l].val;
  33. tree[r].val=-tree[r].val;
  34. swap(tree[l].mx,tree[l].mn);
  35. tree[l].mx=-tree[l].mx;tree[l].mn=-tree[l].mn;
  36. swap(tree[r].mx,tree[r].mn);
  37. tree[r].mx=-tree[r].mx;tree[r].mn=-tree[r].mn;
  38. }
  39. }
  40. void pushup(int x)
  41. {
  42. int l=tree[x].left,r=tree[x].right;
  43. tree[x].mx=max(tree[l].mx,tree[r].mx);
  44. if(x>n)tree[x].mx=max(tree[x].mx,tree[x].val);
  45. tree[x].mn=min(tree[l].mn,tree[r].mn);
  46. if(x>n)tree[x].mn=min(tree[x].mn,tree[x].val);
  47. }
  48. void rotate(int x)
  49. {
  50. int y=father[x],z=father[y];
  51. if(!isroot(y))
  52. {
  53. if(tree[z].left==y)tree[z].left=x;
  54. else tree[z].right=x;
  55. }
  56. if(tree[y].left==x)
  57. {
  58. father[x]=z;father[y]=x;tree[y].left=tree[x].right;tree[x].right=y;father[tree[y].left]=y;
  59. }
  60. else
  61. {
  62. father[x]=z;father[y]=x;tree[y].right=tree[x].left;tree[x].left=y;father[tree[y].right]=y;
  63. }
  64. pushup(y);pushup(x);
  65. }
  66. void splay(int x)
  67. {
  68. int top=,i,y,z;Stack[++top]=x;
  69. for(i=x;!isroot(i);i=father[i])Stack[++top]=father[i];
  70. for(i=top;i>=;i--)pushdown(Stack[i]);
  71. while(!isroot(x))
  72. {
  73. y=father[x],z=father[y];
  74. if(!isroot(y))
  75. {
  76. if((tree[y].left==x)^(tree[z].left==y))rotate(x);
  77. else rotate(y);
  78. }
  79. rotate(x);
  80. }
  81. }
  82. void access(int x)
  83. {
  84. int last=;
  85. while(x!=)
  86. {
  87. splay(x);
  88. tree[x].right=last;pushup(x);
  89. last=x;x=father[x];
  90. }
  91. }
  92. void makeroot(int x)
  93. {
  94. access(x);splay(x);rev[x]^=;
  95. }
  96. void link(int u,int v)
  97. {
  98. makeroot(u);father[u]=v;splay(u);
  99. }
  100. void cut(int u,int v)
  101. {
  102. makeroot(u);access(v);splay(v);father[u]=tree[v].left=;
  103. }
  104. int findroot(int x)
  105. {
  106. access(x);splay(x);
  107. while(tree[x].left!=)x=tree[x].left;
  108. return x;
  109. }
  110. int main()
  111. {
  112. freopen("maintaintree.in","r",stdin);
  113. freopen("maintaintree.out","w",stdout);
  114. int i,a,b,c;
  115. char fh[];
  116. n=read();
  117. for(i=;i<=*n;i++)tree[i].mx=-INF,tree[i].mn=INF;
  118. for(i=;i<n;i++)
  119. {
  120. a=read();b=read();c=read();
  121. tree[n+i].mx=tree[n+i].mn=tree[n+i].val=c;
  122. link(a,n+i);link(n+i,b);
  123. }
  124. while()
  125. {
  126. scanf("\n%s",fh);
  127. if(fh[]=='D')break;
  128. if(fh[]=='Q')
  129. {
  130. a=read();b=read();
  131. makeroot(a);access(b);splay(b);
  132. printf("%d\n",tree[b].mx);
  133. }
  134. else if(fh[]=='C')
  135. {
  136. a=read();b=read();
  137. makeroot(n+a);tree[n+a].mn=tree[n+a].mx=tree[n+a].val=b;
  138. }
  139. else
  140. {
  141. a=read();b=read();
  142. makeroot(a);access(b);splay(b);
  143. tag[b]^=;
  144. swap(tree[b].mx,tree[b].mn);
  145. tree[b].val=-tree[b].val;
  146. tree[b].mx=-tree[b].mx;
  147. tree[b].mn=-tree[b].mn;
  148. }
  149. }
  150. fclose(stdin);
  151. fclose(stdout);
  152. return ;
  153. }

2016.3.24

补一发树链剖分:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define MAXN 10010
  4. #define INF 1e9
  5. struct node
  6. {
  7. int begin,end,value,next;
  8. }edge[*MAXN];
  9. struct NODE
  10. {
  11. int left,right,mx,mn,tag;
  12. }tree[*MAXN];
  13. 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;
  14. bool vis[MAXN];
  15. void addedge(int bb,int ee,int vv)
  16. {
  17. edge[++cnt].begin=bb;edge[cnt].end=ee;edge[cnt].value=vv;edge[cnt].next=Head[bb];Head[bb]=cnt;
  18. }
  19. void addedge1(int bb,int ee,int vv)
  20. {
  21. addedge(bb,ee,vv);addedge(ee,bb,vv);
  22. }
  23. int read()
  24. {
  25. int s=,fh=;char ch=getchar();
  26. while(ch<''||ch>''){if(ch=='-')fh=-;ch=getchar();}
  27. while(ch>=''&&ch<=''){s=s*+(ch-'');ch=getchar();}
  28. return s*fh;
  29. }
  30. void dfs1(int u)
  31. {
  32. int i,v;
  33. size[u]=;vis[u]=true;
  34. for(i=Head[u];i!=-;i=edge[i].next)
  35. {
  36. v=edge[i].end;
  37. if(vis[v]==false)
  38. {
  39. deep[v]=deep[u]+;
  40. P[v][]=u;
  41. dfs1(v);
  42. size[u]+=size[v];
  43. }
  44. }
  45. }
  46. void Ycl()
  47. {
  48. int i,j;
  49. for(j=;(<<j)<=n;j++)
  50. {
  51. for(i=;i<=n;i++)
  52. {
  53. if(P[i][j-]!=-)P[i][j]=P[P[i][j-]][j-];
  54. }
  55. }
  56. }
  57. void dfs2(int u,int chain)
  58. {
  59. int k=,i,v;
  60. pos[u]=++SIZE;belong[u]=chain;
  61. for(i=Head[u];i!=-;i=edge[i].next)
  62. {
  63. v=edge[i].end;
  64. if(deep[v]>deep[u]&&size[v]>size[k])k=v;
  65. }
  66. if(k==)return;
  67. dfs2(k,chain);
  68. for(i=Head[u];i!=-;i=edge[i].next)
  69. {
  70. v=edge[i].end;
  71. if(deep[v]>deep[u]&&v!=k)dfs2(v,v);
  72. }
  73. }
  74. int LCA(int x,int y)
  75. {
  76. int i,j;
  77. if(deep[x]<deep[y])swap(x,y);
  78. for(i=;(<<i)<=deep[x];i++);i--;
  79. for(j=i;j>=;j--)if(deep[x]-(<<j)>=deep[y])x=P[x][j];
  80. if(x==y)return x;
  81. for(j=i;j>=;j--)
  82. {
  83. if(P[x][j]!=-&&P[x][j]!=P[y][j])
  84. {
  85. x=P[x][j];
  86. y=P[y][j];
  87. }
  88. }
  89. return P[x][];
  90. }
  91. void Pushup(int k)
  92. {
  93. tree[k].mx=max(tree[k*].mx,tree[k*+].mx);
  94. tree[k].mn=min(tree[k*].mn,tree[k*+].mn);
  95. }
  96. void Pushdown(int k)
  97. {
  98. int l=k*,r=k*+;
  99. if(tree[k].tag!=)
  100. {
  101. tree[k].tag^=;tree[l].tag^=;tree[r].tag^=;
  102. swap(tree[l].mn,tree[l].mx);
  103. tree[l].mn=-tree[l].mn;tree[l].mx=-tree[l].mx;
  104. swap(tree[r].mn,tree[r].mx);
  105. tree[r].mn=-tree[r].mn;tree[r].mx=-tree[r].mx;
  106. }
  107. }
  108. void Build(int k,int l,int r)
  109. {
  110. tree[k].left=l;tree[k].right=r;tree[k].mx=-INF;tree[k].mn=INF;tree[k].tag=;
  111. if(l==r)
  112. {
  113. tree[k].mx=tree[k].mn=vv[l];
  114. return;
  115. }
  116. int mid=(l+r)/;
  117. Build(k*,l,mid);Build(k*+,mid+,r);
  118. Pushup(k);
  119. }
  120. void Change(int k,int lr,int C)
  121. {
  122. if(tree[k].left==tree[k].right){tree[k].mx=tree[k].mn=C;return;}
  123. Pushdown(k);
  124. int mid=(tree[k].left+tree[k].right)/;
  125. if(lr<=mid)Change(k*,lr,C);
  126. else Change(k*+,lr,C);
  127. Pushup(k);
  128. }
  129. int Query_max(int k,int l,int r)
  130. {
  131. if(l<=tree[k].left&&tree[k].right<=r)return tree[k].mx;
  132. Pushdown(k);
  133. int mid=(tree[k].left+tree[k].right)/;
  134. if(r<=mid)return Query_max(k*,l,r);
  135. else if(l>mid)return Query_max(k*+,l,r);
  136. else return max(Query_max(k*,l,mid),Query_max(k*+,mid+,r));
  137. }
  138. int Solve_max(int x,int f)
  139. {
  140. int MAX=-INF;
  141. while(belong[x]!=belong[f])
  142. {
  143. MAX=max(MAX,Query_max(,pos[belong[x]],pos[x]));
  144. x=P[belong[x]][];
  145. }
  146. if(x!=f)MAX=max(MAX,Query_max(,pos[f]+,pos[x]));
  147. return MAX;
  148. }
  149. void Negate(int k,int l,int r)
  150. {
  151. if(l<=tree[k].left&&tree[k].right<=r/*tree[k].left==tree[k].right*/)
  152. {
  153. swap(tree[k].mn,tree[k].mx);
  154. tree[k].mn=-tree[k].mn;tree[k].mx=-tree[k].mx;
  155. tree[k].tag^=;
  156. return;
  157. }
  158. Pushdown(k);
  159. int mid=(tree[k].left+tree[k].right)/;
  160. if(r<=mid)Negate(k*,l,r);
  161. else if(l>mid)Negate(k*+,l,r);
  162. else {Negate(k*,l,mid);Negate(k*+,mid+,r);}
  163. Pushup(k);
  164. }
  165. void Solve_negate(int x,int f)
  166. {
  167. while(belong[x]!=belong[f])
  168. {
  169. Negate(,pos[belong[x]],pos[x]);
  170. x=P[belong[x]][];
  171. }
  172. if(x!=f)Negate(,pos[f]+,pos[x]);
  173. }
  174. int main()
  175. {
  176. freopen("maintaintree.in","r",stdin);
  177. freopen("maintaintree.out","w",stdout);
  178. int i,I,W,bb,ee,lca;
  179. char fh[];
  180. n=read();
  181. memset(Head,-,sizeof(Head));cnt=;
  182. for(i=;i<n;i++)
  183. {
  184. U[i]=read();V[i]=read();VAL[i]=read();
  185. addedge1(U[i],V[i],VAL[i]);
  186. }
  187. memset(P,-,sizeof(P));SIZE=;
  188. dfs1();Ycl();
  189. dfs2(,);
  190. for(i=;i<n;i++)
  191. {
  192. if(deep[U[i]]>deep[V[i]])id[i]=U[i];
  193. else id[i]=V[i];
  194. }
  195. for(i=;i<n;i++)vv[pos[id[i]]]=VAL[i];
  196. Build(,,n);
  197. while()
  198. {
  199. scanf("\n%s",fh);
  200. if(fh[]=='D')break;
  201. if(fh[]=='C')
  202. {
  203. I=read();W=read();
  204. Change(,pos[id[I]],W);
  205. }
  206. else if(fh[]=='Q')
  207. {
  208. bb=read();ee=read();
  209. lca=LCA(bb,ee);
  210. printf("%d\n",max(Solve_max(bb,lca),Solve_max(ee,lca)));
  211. }
  212. else
  213. {
  214. bb=read();ee=read();
  215. lca=LCA(bb,ee);
  216. Solve_negate(bb,lca);
  217. Solve_negate(ee,lca);
  218. }
  219. }
  220. fclose(stdin);
  221. fclose(stdout);
  222. return ;
  223. }

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. SQL Server备份还原数据库中的小把戏

    备份数据库时出现一个不太了解的错误 ,错误信息“is formatted to support  1 media families, but 2 media families are expected ...

  2. ExtJs中处理时间,出现NaN-NaN-NaN的解决方式

    关键字: extjs日期格式问题(二) 一般我们的前台代码Ext.grid.ColumnModel里会这样写,以便显示日期格式: Js代码 1.....   2.{header:"birth ...

  3. 解决Oracle clob字段数据过大问题

    select * from user_lobs where table_name='WX_MAIL';--SYS_LOB0001313121C00015$$ MB FROM user_segments ...

  4. 修正constructor的指向

    function Aaa(){ } //Aaa.prototype.constructor = Aaa;   //每一个函数都会有的,都是自动生成的 Aaa.prototype.name = '小明' ...

  5. jquery 只有二级下拉菜单

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. 从一个标准 url 里取出文件的扩展名

    在php预定义函数中有一个叫做"pathinfo()"的函数,专门用于返回文件路径信息的. 那好,我们就来看一下它能为我们做些什么?       语法:pathinfo($url_ ...

  7. JavaScript学习心得(二)

    一选择DOCTYPE DOCTYPE是一种标准通用标记语言的文档类型声明,目的是告诉标准通用标记语言解析器使用什么样的文档类型定义(DTD)来解析文档. 网页从DOCTYPE开始,即<!DOCT ...

  8. 帝国cms7.0跳过[会员注册类型]这步的方法

    改 e/config/config.php 文件,把$ecms_config['member']['changeregisterurl']="ChangeRegister.php" ...

  9. QPixmap,QImage图片大小缩放linux版

    注意事项: 1.装载图片的地址有时候会读取不到.可以多摸索一下当前系统对应的格式. 2.scaled缩放方式选择 3.注意保存路径.下面程序保存路径是当前执行文件目录中. PicOpera::PicO ...

  10. window—BAT脚本

    bat脚本注释方法: 1.:: 注释内容(第一个冒号后也可以跟任何一个非字母数字的字符) 2.rem 注释内容(不能出现重定向符号和管道符号) 3.echo 注释内容(不能出现重定向符号和管道符号)〉 ...