【bzoj2631】tree link-cut-tree

2016-06-01 08:50:36

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2631

注意加和乘的标记下传问题。

还有就是split后,要分清x和y哪个是祖先。

pushup在access和rotate后都要进行。

这题还卡常数,开ll就会T,开unsigned int即可。

  1 #include<bits/stdc++.h>
  2 #define inf 1000000000
  3 #define uint unsigned int
  4 #define N 100005
  5 #define mod 51061
  6 using namespace std;
  7 int read(){
  8   int x=0,f=1;char ch=getchar();
  9   while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
 10   while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
 11   return x*f;
 12 }
 13 int n,q;
 14 char ch[5];
 15 namespace LCT{
 16   int ch[N][2],fa[N],sz[N];bool rev[N];
 17   uint cj[N],add[N],val[N],sum[N];
 18   inline bool isroot(int x){
 19     if(ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x)return 1;return 0;
 20   }
 21   void change(int x,int c,int a){
 22     if(!x)return;
 23     val[x]=(val[x]*c+a)%mod;
 24     sum[x]=(sum[x]*c+a*sz[x])%mod;
 25     add[x]=(add[x]*c+a)%mod;
 26     cj[x]=(cj[x]*c)%mod;
 27   }
 28   void pushdown(int x){
 29     if(rev[x]){
 30       rev[ch[x][0]]^=1;rev[ch[x][1]]^=1;rev[x]^=1;
 31       swap(ch[x][0],ch[x][1]);
 32     }
 33     if(cj[x]!=1||add[x]!=0){
 34       change(ch[x][0],cj[x],add[x]);
 35       change(ch[x][1],cj[x],add[x]);
 36     }
 37     cj[x]=1;add[x]=0;
 38   }
 39   void Pushdown(int x){
 40     if(!isroot(x))Pushdown(fa[x]);
 41     pushdown(x);
 42   }
 43   void pushup(int x){
 44     sum[x]=(sum[ch[x][0]]+sum[ch[x][1]]+val[x])%mod;
 45     sz[x]=(sz[ch[x][0]]+sz[ch[x][1]]+1)%mod;
 46   }
 47   void rotate(int x){
 48     int y=fa[x],k=ch[y][1]==x;
 49     if(!isroot(y))ch[fa[y]][ch[fa[y]][1]==y]=x;
 50     fa[x]=fa[y];
 51     fa[ch[x][!k]]=y;
 52     fa[y]=x;
 53     ch[y][k]=ch[x][!k];
 54     ch[x][!k]=y;
 55     pushup(y);pushup(x);
 56   }
 57   void splay(int x){
 58     Pushdown(x);
 59     for(int y=fa[x];!isroot(x);y=fa[x]){
 60       if(!isroot(y)){
 61         if((ch[fa[y]][ch[fa[y]][1]==y])!=(ch[y][1]==x))rotate(x);
 62         else rotate(y);
 63       }rotate(x);
 64     }
 65   }
 66   inline void access(int x){
 67     int y=0;
 68     while(x){
 69       splay(x);
 70       ch[x][1]=y;pushup(x);
 71       x=fa[y=x];
 72     }
 73   }
 74   inline void moveroot(int x){
 75     access(x);splay(x);rev[x]^=1;
 76   }
 77   inline void link(int x,int y){
 78     moveroot(x);fa[x]=y;splay(x);
 79   }
 80   inline void cut(int x,int y){
 81     moveroot(x);access(y);splay(y);ch[y][0]=fa[x]=0;
 82   }
 83   inline void split(int x,int y){
 84     moveroot(y);access(x);splay(x);
 85   }
 86 }
 87 int main(){
 88   n=read();q=read();
 89   for(int i=1;i<=n;i++)LCT::val[i]=LCT::sum[i]=LCT::cj[i]=LCT::sz[i]=1;
 90   for(int i=1;i<n;i++)LCT::link(read(),read());
 91   while(q--){
 92     scanf("%s",ch);
 93     int u=read(),v=read();
 94     if(ch[0]==‘+‘)LCT::split(u,v),LCT::change(u,1,read());
 95     else if(ch[0]==‘-‘){
 96       LCT::cut(u,v);u=read();v=read();LCT::link(u,v);
 97     }
 98     else if(ch[0]==‘*‘)LCT::split(u,v),LCT::change(u,read(),0);
 99     else LCT::split(u,v),printf("%d\n",LCT::sum[u]%mod);
100   }
101   return 0;
102 }

2631: tree

Time Limit: 30 Sec  Memory Limit: 128 MB
Submit: 3385  Solved: 1137
[Submit][Status][Discuss]

Description

 一棵n个点的树,每个点的初始权值为1。对于这棵树有q个操作,每个操作为以下四种操作之一:
+ u v c:将u到v的路径上的点的权值都加上自然数c;
- u1 v1 u2 v2:将树中原有的边(u1,v1)删除,加入一条新边(u2,v2),保证操作完之后仍然是一棵树;
* u v c:将u到v的路径上的点的权值都乘上自然数c;
/ u v:询问u到v的路径上的点的权值和,求出答案对于51061的余数。

Input

  第一行两个整数n,q
接下来n-1行每行两个正整数u,v,描述这棵树
接下来q行,每行描述一个操作

Output

  对于每个/对应的答案输出一行

Sample Input

3 2
1 2
2 3
* 1 3 4
/ 1 1

Sample Output

4

HINT

数据规模和约定

10%的数据保证,1<=n,q<=2000

另外15%的数据保证,1<=n,q<=5*10^4,没有-操作,并且初始树为一条链

另外35%的数据保证,1<=n,q<=5*10^4,没有-操作

100%的数据保证,1<=n,q<=10^5,0<=c<=10^4

时间: 2024-10-11 06:50:11

【bzoj2631】tree link-cut-tree的相关文章

【BZOJ 3282】Tree Link Cut Tree模板题

知道了为什么要换根(changeroot),access后为什么有时要splay,以及LCT的其他操作,算是比较全面的啦吧,,, 现在才知道这些,,,真心弱,,, #include<cstdio> #include<algorithm> #define read(x) x=getint() using namespace std; const int N=300003; inline int getint(){char c;int ret=0;for(c=getchar();c&l

AC日记——【模板】Link Cut Tree 洛谷 P3690

[模板]Link Cut Tree 思路: LCT模板: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 300005 int n,m,val[maxn]; int top,ch[maxn][2],f[maxn],xr[maxn],q[maxn],rev[maxn]; inline void in(int &now) { int if_z=1;now=0; char Cget=getchar(); while

LuoguP3690 【模板】Link Cut Tree (动态树) LCT模板

P3690 [模板]Link Cut Tree (动态树) 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和.保证x到y是联通的. 1:后接两个整数(x,y),代表连接x到y,若x到y已经联通则无需连接. 2:后接两个整数(x,y),代表删除边(x,y),不保证边(x,y)存在. 3:后接两个整数(x,y),代表将点x上的权值变成y. 输入输出

P3690 【模板】Link Cut Tree (动态树)

P3690 [模板]Link Cut Tree (动态树) https://www.luogu.org/problemnew/show/P3690 分析: LCT模板 代码: 注意一下cut! 1 #include<cstdio> 2 #include<algorithm> 3 4 using namespace std; 5 6 const int N = 300100; 7 8 int val[N],fa[N],ch[N][2],rev[N],sum[N],st[N],top;

【BZOJ2816】【ZJOI2012】网络(Link-Cut Tree)

[BZOJ2816][ZJOI2012]网络(Link-Cut Tree) 题面 题目描述 有一个无向图G,每个点有个权值,每条边有一个颜色.这个无向图满足以下两个条件: 对于任意节点连出去的边中,相同颜色的边不超过两条. 图中不存在同色的环,同色的环指相同颜色的边构成的环. 在这个图上,你要支持以下三种操作: 修改一个节点的权值. 修改一条边的颜色. 查询由颜色c的边构成的图中,所有可能在节点u到节点v之间的简单路径上的节点的权值的最大值. 输入输出格式 输入格式: 输入文件network.i

【SPOJ】QTREE7(Link-Cut Tree)

[SPOJ]QTREE7(Link-Cut Tree) 题面 洛谷 Vjudge 题解 和QTREE6的本质是一样的:维护同色联通块 那么,QTREE6同理,对于两种颜色分别维护一棵\(LCT\) 每次只修改和它父亲的连边. 考虑如何维护最大值 因为每次\(access\)会删去一个数,所以我们肯定不能够只维护最大值. 因此,对于每一个节点,额外维护一个\(multiset\)(当然,可删堆,\(map\)之类的也行) 每次用\(multiset\)维护虚子树的最值,拿过去更新即可. 最后的答案

Codeforces Round #339 (Div. 2) A. Link/Cut Tree

A. Link/Cut Tree Programmer Rostislav got seriously interested in the Link/Cut Tree data structure, which is based on Splay trees. Specifically, he is now studying the expose procedure. Unfortunately, Rostislav is unable to understand the definition

【DataStructure】Implemantation of Binary Tree

Statements: This blog was written by me, but most of content  is quoted from book[Data Structure with Java Hubbard] Here is a class for binary trees that directly implements the recursive definition. By extending the AbstractCollectionclass, it remai

【LeetCode】Validate Binary Search Tree

Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is defined as follows: The left subtree of a node contains only nodes with keys less than the node's key. The right subtree of a node contains only nodes with keys

【BZOJ2870】最长道路tree 点分治+树状数组

[BZOJ2870]最长道路tree Description H城很大,有N个路口(从1到N编号),路口之间有N-1边,使得任意两个路口都能互相到达,这些道路的长度我们视作一样.每个路口都有很多车辆来往,所以每个路口i都有一个拥挤程度v[i],我们认为从路口s走到路口t的痛苦程度为s到t的路径上拥挤程度的最小值,乘上这条路径上的路口个数所得的积.现在请你求出痛苦程度最大的一条路径,你只需输出这个痛苦程度. 简化版描述: 给定一棵N个点的树,求树上一条链使得链的长度乘链上所有点中的最小权值所得的积