Time Limit: 5000MS | Memory Limit: 131072K | |
Total Submissions: 12247 | Accepted: 3151 |
Description
You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbered 1 through N − 1. Each edge is associated with a weight. Then you are to execute a series of instructions on the tree. The instructions can be one of the following forms:
CHANGE i v |
Change the weight of the ith edge to v |
NEGATE a b |
Negate the weight of every edge on the path from a to b |
QUERY a b |
Find the maximum weight of edges on the path from a to b |
Input
The input contains multiple test cases. The first line of input contains an integer t (t ≤ 20), the number of test cases. Then follow the test cases.
Each test case is preceded by an empty line. The first nonempty line of its contains N (N ≤ 10,000). The next N − 1 lines each contains three integers a, b and c, describing an edge connecting nodes a and b with weight c. The edges are numbered in the order they appear in the input. Below them are the instructions, each sticking to the specification above. A lines with the word “DONE
” ends the test case.
Output
For each “QUERY
” instruction, output the result on a separate line.
Sample Input
1 3 1 2 1 2 3 2 QUERY 1 2 CHANGE 1 3 QUERY 1 2 DONE
Sample Output
1 3
Source
题意就是: 有T组数据 ,给你n个点的树,有三种操作:
1.CHANGE i v :将第i条边的值改为v
2.NEGATE a b :将a点到b点路径上的边权取反
3.QUERY a b :查询a点到b点路径上最大的边权值,
由于有取反操作,记录最大和最小值 然后取反并交换就可以,用线段树来维护,真香警告。。。
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<bitset> 6 #include<cassert> 7 #include<cctype> 8 #include<cmath> 9 #include<cstdlib> 10 #include<ctime> 11 #include<deque> 12 #include<iomanip> 13 #include<list> 14 #include<map> 15 #include<queue> 16 #include<set> 17 #include<stack> 18 #include<vector> 19 using namespace std; 20 typedef long long ll; 21 22 const double PI=acos(-1.0); 23 const double eps=1e-6; 24 const ll mod=1e9+7; 25 const int inf=0x3f3f3f3f; 26 const int maxn=1e4+10; 27 const int maxm=100+10; 28 #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 29 #define lson l,m,rt<<1 30 #define rson m+1,r,rt<<1|1 31 32 int head[maxn],cnt,num,n; 33 34 struct Edge{ 35 int to,next; 36 }edge[maxn<<1]; 37 38 void add(int u,int v)//存图(树) 39 { 40 edge[cnt].to=v; 41 edge[cnt].next=head[u]; 42 head[u]=cnt++; 43 } 44 45 int val[maxn],siz[maxn],dep[maxn],son[maxn]; 46 int top[maxn],tid[maxn],pos[maxn],fa[maxn]; 47 48 void init()//初始化 49 { 50 memset(head,-1,sizeof(head)); 51 memset(son,-1,sizeof(son)); 52 cnt=num=0; 53 } 54 55 ///树链剖分部分 56 void dfs1(int u,int father)//第一遍dfs,可以得到当前节点的父亲节点,当前节点的深度,当前节点的重儿子 57 { 58 //更新dep,fa,siz数组 59 siz[u]=1;//保存以u为根的子树节点个数 60 fa[u]=father;//保存爸爸 61 dep[u]=dep[father]+1;//记录深度 62 for(int i=head[u];~i;i=edge[i].next){//遍历所有和当前节点连接的节点 63 int v=edge[i].to; 64 if(v!=father){//如果连接的是当前节点的父亲节点,则不处理 65 dfs1(v,u); 66 siz[u]+=siz[v];//直接子树节点相加,当前节点的size加上子节点的size 67 if(son[u]==-1||siz[v]>siz[son[u]])//如果没有设置过重节点son或者子节点v的size大于之前记录的重节点son,进行更新 68 son[u]=v;//保存重儿子 69 } 70 } 71 } 72 73 void dfs2(int u,int tp)//将各个重节点连接成重链,轻节点连接成轻链,并且将重链(区间)用数据结构(一般是树状数组或者线段树)来维护,并且为每个节点进行编号,其实就是dfs在执行时的顺序(tid数组),以及当前节点所在链的起点(top数组)还有当前节点在树中的位置(pos) ) 74 { 75 top[u]=tp;//保存当前节点所在的链的顶端节点,当前节点的起点 76 tid[u]=++num;//保存树中每个节点剖分以后的新编号(dfs的执行顺序) 77 pos[tid[u]]=u;//保存当前节点在树中的位置,设置dfs序号对应成当前节点 78 if(son[u]==-1) return ;//如果当前节点没有处在重链上,则不处理 79 dfs2(son[u],tp);//将这条重链上的所有节点都设置成起始的重节点 80 for(int i=head[u];~i;i=edge[i].next){//遍历所有和当前节点连接的节点 81 int v=edge[i].to;//如果连接节点不是当前节点的重节点并且也不是u的父节点,则将其的top设置成自己,进一步递归 82 if(v!=son[u]&&v!=fa[u]) 83 dfs2(v,v); 84 } 85 } 86 87 int lazy[maxn<<2],Max[maxn<<2],Min[maxn<<2]; 88 89 //线段树部分 90 void Swap(int &x,int &y){int t=x;x=-y;y=-t;} 91 92 void pushup(int rt) 93 { 94 Max[rt]=max(Max[rt<<1],Max[rt<<1|1]); 95 Min[rt]=min(Min[rt<<1],Min[rt<<1|1]); 96 } 97 98 void pushdown(int rt) 99 { 100 if(lazy[rt]){ 101 lazy[rt<<1]+=lazy[rt]; 102 lazy[rt<<1|1]+=lazy[rt]; 103 if(lazy[rt]&1){ //两个子区间是否取反依靠当前区间的懒惰标记判断,判断奇偶 104 Swap(Max[rt<<1],Min[rt<<1]); 105 Swap(Max[rt<<1|1],Min[rt<<1|1]); 106 } 107 lazy[rt]=0; 108 } 109 } 110 111 void build(int l,int r,int rt) 112 { 113 lazy[rt]=0; 114 if(l==r){ 115 Max[rt]=Min[rt]=0; 116 return ; 117 } 118 119 int m=(l+r)>>1; 120 build(lson); 121 build(rson); 122 pushup(rt); 123 } 124 125 void update(int pos,int val,int l,int r,int rt) 126 { 127 if(l==r&&l==pos){ 128 Max[rt]=val;Min[rt]=val;lazy[rt]=0; 129 return ; 130 } 131 132 pushdown(rt); 133 int m=(l+r)>>1; 134 if(pos<=m) update(pos,val,lson); 135 else update(pos,val,rson); 136 pushup(rt); 137 } 138 139 void Negate(int L,int R,int l,int r,int rt)//Negate是int tmp=Max,Max=-Min,Min=-tmp 140 { 141 if(L<=l&&r<=R){ 142 lazy[rt]++; 143 Swap(Max[rt],Min[rt]);//这里要马上取反 144 return ; 145 } 146 147 pushdown(rt); 148 int m=(l+r)>>1; 149 if(L<=m) Negate(L,R,lson); 150 if(R> m) Negate(L,R,rson); 151 pushup(rt); 152 } 153 154 int query(int L,int R,int l,int r,int rt) 155 { 156 if(L<=l&&r<=R){ 157 return Max[rt]; 158 } 159 160 pushdown(rt); 161 int ret=-inf; 162 int m=(l+r)>>1; 163 if(L<=m) ret=max(ret,query(L,R,lson)); 164 if(R> m) ret=max(ret,query(L,R,rson)); 165 pushup(rt); 166 return ret; 167 } 168 169 int get_max(int u,int v) 170 { 171 int ans=-1<<30; 172 while(top[u]!=top[v]){ 173 if(dep[top[u]]<dep[top[v]]) swap(u,v); 174 ans=max(ans,query(tid[top[u]],tid[u],1,n,1)); 175 u=fa[top[u]]; 176 } 177 178 if(dep[v]<dep[u]) swap(u,v); 179 ans=max(ans,query(tid[son[u]],tid[v],1,n,1));//这里写捞了,tid[son[u]],写成tid[u],wa了好几天。。。 180 printf("%d ",ans); 181 } 182 183 void change(int u,int v) 184 { 185 while(top[u]!=top[v]){ 186 if(dep[top[u]]<dep[top[v]]) swap(u,v); 187 Negate(tid[top[u]],tid[u],1,n,1); 188 u=fa[top[u]]; 189 } 190 191 if(u==v) return ; 192 if(dep[v]<dep[u]) swap(u,v); 193 Negate(tid[son[u]],tid[v],1,n,1); 194 } 195 196 struct eg{ 197 int u,v,val; 198 }eg[maxn]; 199 200 int main() 201 { 202 int t; 203 scanf("%d",&t); 204 while(t--){ 205 scanf("%d",&n); 206 init(); 207 for(int i=1;i<n;i++){ 208 scanf("%d%d%d",&eg[i].u,&eg[i].v,&eg[i].val); 209 add(eg[i].u,eg[i].v);//加边 210 add(eg[i].v,eg[i].u);//加边 211 } 212 dfs1(1,0);//第一遍dfs 213 dfs2(1,1);//第二遍dfs 214 build(1,n,1); 215 for(int i=1;i<n;i++){ 216 if(dep[eg[i].u]<dep[eg[i].v]) swap(eg[i].u,eg[i].v); 217 update(tid[eg[i].u],eg[i].val,1,n,1); 218 } 219 int a,b; 220 char op[10]; 221 while(scanf("%s",op)&&op[0]!='D'){ 222 scanf("%d%d",&a,&b); 223 if(op[0]=='Q'){ 224 get_max(a,b); 225 } 226 if(op[0]=='C'){ 227 update(tid[eg[a].u],b,1,n,1); 228 } 229 if(op[0]=='N'){ 230 change(a,b); 231 } 232 } 233 } 234 }
哈哈哈哈,加油加油。