poj 3237 Tree(树链剖分,线段树)
2016-02-10 22:56
381 查看
Tree
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:
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 “
Output
For each “
Sample Input
Sample Output
Source
POJ Monthly--2007.06.03, Lei, Tao
【思路】
树链剖分,线段树。
又练了一边线段树<_<,bug满天飞T^T,线段树还得再做点题。
线段树:维护mx mn分别代表线段最大最小值,对于NEGATE操作打一个f标记,作用时直接将mx mn取负后交换即可。注意一下pushdown和maintain。
【代码】
Time Limit: 5000MS | Memory Limit: 131072K | |
Total Submissions: 7268 | Accepted: 1969 |
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:
CHANGEi v | Change the weight of the ith edge to v |
NEGATEa b | Negate the weight of every edge on the path from a to b |
QUERYa b | Find the maximum weight of edges on the path from a to b |
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
POJ Monthly--2007.06.03, Lei, Tao
【思路】
树链剖分,线段树。
又练了一边线段树<_<,bug满天飞T^T,线段树还得再做点题。
线段树:维护mx mn分别代表线段最大最小值,对于NEGATE操作打一个f标记,作用时直接将mx mn取负后交换即可。注意一下pushdown和maintain。
【代码】
#include<cstdio> #include<cstring> #include<vector> #include<iostream> #include<algorithm> #define FOR(a,b,c) for(int a=(b);a<=(c);a++) using namespace std; const int N = 50000+10; const int INF = 1e9; struct Node { int l,r,mx,mn,f; }T[N<<1]; struct Edge { int u,v,w; Edge(int u=0,int v=0,int w=0) :u(u),v(v),w(w) {}; }; int n,q,z,d [3]; vector<Edge> es; vector<int> g ; void adde(int u,int v,int w) { es.push_back(Edge(u,v,w)); int m=es.size(); g[u].push_back(m-1); } //INIT int top ,son ,dep ,fa ,siz ,w ; void dfs1(int u) { son[u]=0; siz[u]=1; for(int i=0;i<g[u].size();i++) { int v=es[g[u][i]].v; //1 if(v!=fa[u]) { fa[v]=u , dep[v]=dep[u]+1; dfs1(v); siz[u]+=siz[v]; if(siz[v]>siz[son[u]]) son[u]=v; } } } void dfs2(int u,int tp) { top[u]=tp; w[u]=++z; if(son[u]) dfs2(son[u],tp); for(int i=0;i<g[u].size();i++) { int v=es[g[u][i]].v; if(v!=fa[u] && v!=son[u]) dfs2(v,v); } } //SEGMENT TREE //标记 该结点已被作用而子结点仍未作用 //pushdown 作用于访问节点 即只要访问就pushdown void pushdown(int u) { //下传标记 同时作用于子结点 if(T[u].f && T[u].l<T[u].r) { int lc=u<<1,rc=lc|1; T[u].f=0; T[lc].f^=1 ,T[rc].f^=1; int t; t=T[lc].mn,T[lc].mn=-T[lc].mx,T[lc].mx=-t; t=T[rc].mn,T[rc].mn=-T[rc].mx,T[rc].mx=-t; } } void maintain(int u) { T[u].mx=max(T[u<<1].mx,T[u<<1|1].mx); T[u].mn=min(T[u<<1].mn,T[u<<1|1].mn); } void build(int u,int L,int R) { T[u].l=L,T[u].r=R; T[u].mn=INF , T[u].mx=-INF , T[u].f=0; if(L==R) return ; //2 int M=(L+R)>>1; build(u<<1,L,M) , build(u<<1|1,M+1,R); } void change(int u,int r,int x) { pushdown(u); //6 if(T[u].l==T[u].r) T[u].mn=T[u].mx=x; else { int M=(T[u].l+T[u].r)>>1; //3 if(r<=M) change(u<<1,r,x); else change(u<<1|1,r,x); maintain(u); } } void Negate(int u,int L,int R) { pushdown(u); if(L<=T[u].l && T[u].r<=R) {//打标记 同时作用于当前结点 T[u].f=1; int t; t=T[u].mn,T[u].mn=-T[u].mx,T[u].mx=-t; //4 } else { int M=(T[u].l+T[u].r)>>1; if(L<=M) Negate(u<<1,L,R); if(M<R) Negate(u<<1|1,L,R); maintain(u); } } int query(int u,int L,int R) { pushdown(u); if(L<=T[u].l && T[u].r<=R) return T[u].mx; else { int M=(T[u].l+T[u].r)>>1; int ans=-INF; if(L<=M) ans=max(ans,query(u<<1,L,R)); if(M<R) ans=max(ans,query(u<<1|1,L,R)); return ans; } } //树链剖分 void modify(int u,int v) { while(top[u]!=top[v]) { if(dep[top[u]]<dep[top[v]]) swap(u,v); Negate(1,w[top[u]],w[u]); u=fa[top[u]]; } if(u==v) return ; if(dep[u]>dep[v]) swap(u,v); Negate(1,w[son[u]],w[v]); //5 } int query(int u,int v) { int mx=-INF; while(top[u]!=top[v]) { if(dep[top[u]]<dep[top[v]]) swap(u,v); mx=max(mx,query(1,w[top[u]],w[u])); u=fa[top[u]]; } if(u==v) return mx; if(dep[u]>dep[v]) swap(u,v); mx=max(mx,query(1,w[son[u]],w[v])); return mx; } void read(int& x) { char c=getchar(); while(!isdigit(c)) c=getchar(); x=0; while(isdigit(c)) x=x*10+c-'0' , c=getchar(); } int main() { //freopen("in.in","r",stdin); //freopen("out.out","w",stdout); int T; read(T); while(T--) { read(n); z=0; es.clear(); FOR(i,0,n) g[i].clear(); int u,v,c; FOR(i,1,n-1) { read(u),read(v),read(c); d[i][0]=u,d[i][1]=v,d[i][2]=c; adde(u,v,c),adde(v,u,c); } dfs1(1),dfs2(1,1); build(1,1,z); FOR(i,1,n-1) { if(dep[d[i][1]]<dep[d[i][0]]) swap(d[i][0],d[i][1]); change(1,w[d[i][1]],d[i][2]); } char s[10]; while(scanf("%s",s)==1 && s[0]!='D') { read(u),read(v); if(s[0]=='C') change(1,w[d[u][1]],v); else if(s[0]=='N') modify(u,v); else printf("%d\n",query(u,v)); } } return 0; }
相关文章推荐
- [Spring实战系列](15)使用Spring基于Java的配置
- 若想成功,请记住!
- High CPU Usage 原因及分析
- 在自定义drawRect setBackground不起作用的原因
- Android TV Study 1-1
- 597C. Subsequences【DP】【树状数组】
- [转] JPQL
- The Java™ Tutorials — Concurrency :Defining and Starting a Thread 线程的定义和启动
- 原子位操作
- 245,键盘处理
- 《Python学习手册》(二)
- 有哪些软件堪称「神器」,却不被大众所知?(转)
- QT选择文件对话框实现多种类型文件匹配过滤
- iOS中使用RegexKitLite来试用正则表达式 使用ARC 20个错误解决办法
- js 中的流程控制-循环(for)语句
- CodeForces 266A Stones on the Table
- 华为路由器DCHP服务配置实验(二)
- 华为路由器DCHP服务配置实验(一)
- 线程和指针
- poj2406—KMP next数组的性质求最小周期