POJ 3237 Tree(树链剖分 线段树区间标记)
来源:互联网 发布:杭州龙蛇网络 编辑:程序博客网 时间:2024/05/21 10:47
题意:
一棵树
三种操作
1.改变某条边的权值
2.a到b的路径取反
3,询问a到b路径上的最大值
分析:
树链剖分
线段树维护最大最小值,标记取反
代码量大
#include<cstring>#include<string>#include<iostream>#include<queue>#include<cstdio>#include<algorithm>#include<map>#include<cstdlib>#include<cmath>#include<vector>//#pragma comment(linker, "/STACK:1024000000,1024000000");using namespace std;#define INF 0x3f3f3f3f#define maxn 20004int x[maxn],y[maxn];int fir[maxn],nex[maxn],v[maxn],w[maxn],e_max;int son[maxn],fa[maxn],siz[maxn],deep[maxn],top[maxn],pos[maxn],tot;int val1[maxn],val2[maxn],mi[4*maxn],mx[4*maxn],tag[4*maxn];void init_(){ val1[0]=val1[1]=0; memset(fir,-1,sizeof fir); memset(son,-1,sizeof son); memset(siz,0,sizeof siz); e_max=0; tot=1;}void add_edge(int s,int t,int c){ int e=e_max++; v[e]=t; w[e]=c; nex[e]=fir[s]; fir[s]=e;}void dfs1(int k,int pre,int d){ deep[k]=d; siz[k]++; fa[k]=pre; for(int i=fir[k];~i;i=nex[i]) { int e=v[i]; if(e!=pre) { val1[e]=w[i]; dfs1(e,k,d+1); siz[k]+=siz[e]; if(son[k]==-1||siz[son[k]]<siz[e]) son[k]=e; } }}void dfs2(int k,int sp){ top[k]=sp; pos[k]=tot++; val2[pos[k]]=val1[k]; if(son[k]==-1) return; dfs2(son[k],sp); for(int i=fir[k];~i;i=nex[i]) { int e=v[i]; if(e!=fa[k]&&e!=son[k]) { dfs2(e,e); } }}void pushup(int k){ mx[k]=max(mx[k<<1],mx[k<<1|1]); mi[k]=min(mi[k<<1],mi[k<<1|1]);}void pushdown(int k){ if(!tag[k]) return ; tag[k<<1]^=1; tag[k<<1|1]^=1; swap(mx[k<<1],mi[k<<1]); mx[k<<1]=-mx[k<<1]; mi[k<<1]=-mi[k<<1]; swap(mx[k<<1|1],mi[k<<1|1]); mx[k<<1|1]=-mx[k<<1|1]; mi[k<<1|1]=-mi[k<<1|1]; tag[k]=0;}void init(int l,int r,int k){ tag[k]=0; if(l==r) { mi[k]=mx[k]=val2[l]; return ; } int mid=l+r>>1; init(l,mid,k<<1); init(mid+1,r,k<<1|1); pushup(k);}void update1(int d,int s,int l,int r,int k){ if(s==l&&s==r) { mi[k]=mx[k]=d; return ; } pushdown(k); int mid=l+r>>1; if(s<=mid) update1(d,s,l,mid,k<<1); else update1(d,s,mid+1,r,k<<1|1); pushup(k);}void update2(int d,int s,int t,int l,int r,int k){ if(s==l&&r==t) { tag[k]^=d; swap(mx[k],mi[k]); mx[k]=-mx[k]; mi[k]=-mi[k]; return ; } pushdown(k); int mid=l+r>>1; if(t<=mid) update2(d,s,t,l,mid,k<<1); else if(s>mid) update2(d,s,t,mid+1,r,k<<1|1); else { update2(d,s,mid,l,mid,k<<1); update2(d,mid+1,t,mid+1,r,k<<1|1); } pushup(k);}int query(int s,int t,int l,int r,int k){ if(s==l&&r==t) { return mx[k]; } pushdown(k); int mid=l+r>>1; if(t<=mid) return query(s,t,l,mid,k<<1); else if(s>mid) return query(s,t,mid+1,r,k<<1|1); else return max(query(s,mid,l,mid,k<<1),query(mid+1,t,mid+1,r,k<<1|1));}void Query(int s,int t){ if(s==t) { printf("0\n"); return ; } int ans=-INF; int f1=top[s],f2=top[t]; while(f1!=f2) { if(deep[f1]<deep[f2]) swap(f1,f2),swap(s,t); ans=max(ans,query(pos[f1],pos[s],1,tot-1,1)); s=fa[f1]; f1=top[s]; } if(s==t) { printf("%d\n",ans); return ; } if(deep[s]>deep[t]) swap(s,t); ans=max(ans,query(pos[s]+1,pos[t],1,tot-1,1)); printf("%d\n",ans);}void Change(int s,int t){ int f1=top[s],f2=top[t]; while(f1!=f2) { if(deep[f1]<deep[f2]) swap(f1,f2),swap(s,t); update2(1,pos[f1],pos[s],1,tot-1,1); s=fa[f1]; f1=top[s]; } if(s==t) return ; if(deep[s]>deep[t]) swap(s,t); update2(1,pos[s]+1,pos[t],1,tot-1,1);}int main(){ int T; scanf("%d",&T); while(T--) { init_(); int n; scanf("%d",&n); for(int i=1;i<n;i++) { int c; scanf("%d%d%d",&x[i],&y[i],&c); add_edge(x[i],y[i],c); add_edge(y[i],x[i],c); } dfs1(1,-1,1); dfs2(1,1); init(1,tot-1,1); char s[10]; while(scanf("%s",s)!=EOF&&strcmp(s,"DONE")) { if(!strcmp(s,"QUERY")) { int l,r; scanf("%d%d",&l,&r); Query(l,r); } else if(!strcmp(s,"CHANGE")) { int i,ti; scanf("%d%d",&i,&ti); if(deep[x[i]]<deep[y[i]]) swap(x[i],y[i]); update1(ti,pos[x[i]],1,tot-1,1); } else { int l,r; scanf("%d%d",&l,&r); Change(l,r); } } } return 0;}
0 0
- POJ 3237 Tree(树链剖分 线段树区间标记)
- POJ 3667 Hotel(线段树+区间合并+延迟标记)
- POJ 3237Tree(树链剖分-线段树点更新-区间更新-区间最值查询-入边)
- POJ 3237 Tree(树链剖分+线段树)
- POJ 3237 Tree (树链剖分+线段树)
- POJ 3237 Tree(树链剖分+线段树)
- POJ 3237 Tree (树链剖分+线段树)
- POJ 3468 线段树 区间操作 懒惰标记
- POJ 3667 线段树 + 延迟标记 + 区间处理
- POJ 3468-A Simple Problem with Integers(线段树_区间更新+lazy标记)
- Poj 3468 A Simple Problem with Integers(线段树 区间更新 延迟标记)
- 线段树 (区间修改 区间查询 延迟标记)
- POJ 3237 Tree (树链剖分+线段树)
- |poj 3237|树链剖分|线段树|Tree
- poj 3237 Tree 树链剖分 线段树
- 郁闷的出纳员 (splay的区间标记模板,删除区间,add标记,类似线段树)
- poj 3237 Tree 树链剖分+lazy标记
- POJ 3321 Apple Tree(DFS序+线段树单点修改区间查询)
- LeetCode 232. Implement Queue using Stacks
- mysql -- 常见异常的解决办法导引
- Java基础学习第三天
- Ubuntu修改swap交换空间
- 有关链表的常见题型
- POJ 3237 Tree(树链剖分 线段树区间标记)
- 数组与对象的相互转化
- 【NOIP2016提高A组模拟7.17】锦标赛
- C++链表的建立,排序,删除
- Hadoop多文件输出:MultipleOutputFormat和MultipleOutputs深究(二)
- HTTP的协议解析
- display:inline、block、inline-block
- 【模板大法好】预处理组合数模板
- 【Effective C++读书笔记】篇八(条款18~条款21)