【Codevs3306】水果姐逛水果街Ⅲ 树链剖分
2015-12-16 14:11
363 查看
改!了!好!多!天!
线段树尝试了下zkw,也算有所收获
注释有空再加
线段树尝试了下zkw,也算有所收获
注释有空再加
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<vector> using namespace std; #define pb push_back const int inf=1047483647; int n,m,fa[200010],top[200010],v[200010],w[200010],siz[200010],son[200010],f[1000010][4],ans,maxp,cntw,dep[200010],maxv,minv; vector<int> a[200010]; void init(){ for (maxp=1;maxp<=n+2;maxp<<=1); f[maxp][0]=-inf;f[maxp][1]=inf; f[maxp*2-1][0]=-inf;f[maxp*2-1][1]=inf; } void dfs1(int ro){ int y; siz[ro]=1;son[ro]=0; for (int i=0;i<a[ro].size();i++) { y=a[ro][i]; if (y==fa[ro]) continue; fa[y]=ro;dep[y]=dep[ro]+1;dfs1(y); siz[ro]+=siz[y]; if (siz[y]>siz[son[ro]]) son[ro]=y; } return ; } void dfs2(int ro){ int y; if (ro>1) w[ro]=++cntw; if (son[ro]) { top[son[ro]]=top[ro]; dfs2(son[ro]); } for (int i=0;i<a[ro].size();i++){ y=a[ro][i]; if (y==son[ro]||y==fa[ro]) continue; top[y]=y;dfs2(y); } } void zkw_ins_single(int pos,int value){ int tmp=maxp+pos; f[tmp][0]=value;f[tmp][1]=value;f[tmp][2]=f[tmp][3]=0; tmp>>=1; for (;tmp>=1;tmp>>=1){ f[tmp][0]=max(f[tmp*2][0],f[tmp*2+1][0]); f[tmp][1]=min(f[tmp*2][1],f[tmp*2+1][1]); f[tmp][2]=max(f[tmp*2][0]-f[tmp*2+1][1],max(f[tmp*2][2],f[tmp*2+1][2])); f[tmp][3]=max(f[tmp*2+1][0]-f[tmp*2][1],max(f[tmp*2][3],f[tmp*2+1][3])); } } int zkw_query(int ty,int l,int r){ l=maxp+l-1;r=maxp+r+1; int tmp,tmp1,tmp2; if (ty==0) tmp=inf; else tmp=-inf; tmp1=-inf;tmp2=inf; for (;r-l>1;l>>=1,r>>=1){ if (~l&1) ans=max(ans,f[l+1][2+ty]); if (r&1) ans=max(ans,f[r-1][2+ty]); if (ty==0) { if (~l&1) { tmp=min(tmp,f[l+1][1]); ans=max(ans,tmp1-f[l+1][1]); tmp1=max(tmp1,f[l+1][0]); } if (r&1) { tmp=min(tmp,f[r-1][1]); ans=max(ans,f[r-1][0]-tmp2); tmp2=min(tmp2,f[r-1][1]); } } else { if (r&1) { tmp=max(tmp,f[r-1][0]); ans=max(ans,tmp1-f[r-1][1]); tmp1=max(tmp1,f[r-1][0]); } if (~l&1) { tmp=max(tmp,f[l+1][0]); ans=max(ans,f[l+1][0]-tmp2); tmp2=min(tmp2,f[l+1][1]); } } if (~l&1) { ans=max(ans,f[l+1][0]-minv); ans=max(ans,maxv-f[l+1][1]); } if (r&1){ ans=max(ans,f[r-1][0]-minv); ans=max(ans,maxv-f[r-1][1]); } } ans=max(ans,tmp1-tmp2); return tmp; } void query(int x,int y){ ans=0;maxv=-inf;minv=inf; int d=0; while (x!=y){ if (top[x]==top[y]){ if (dep[x]>dep[y]){ swap(x,y);d^=1; } if (d==0) minv=min(minv,zkw_query(0,w[x]+1,w[y])); else maxv=max(maxv,zkw_query(1,w[x]+1,w[y])); y=x;break; } if (dep[top[x]]>dep[top[y]]){ swap(x,y);d^=1; } if (top[y]==y){ if (d==0) minv=min(minv,v[y]); else maxv=max(maxv,v[y]); ans=max(ans,max(maxv-v[y],v[y]-minv)); y=fa[y];continue; } if (d==0) minv=min(minv,zkw_query(0,w[top[y]]+1,w[y])); else maxv=max(maxv,zkw_query(1,w[top[y]]+1,w[y])); y=top[y]; } maxv=max(maxv,v[x]);minv=min(minv,v[x]); ans=max(ans,maxv-minv); } int main(){ scanf("%d",&n); init(); for (int i=1;i<=n;i++) scanf("%d",&v[i]); for (int i=1;i<=n;i++) v[i]=-v[i]; int x,y,z; for (int i=1;i<n;i++) { scanf("%d%d",&x,&y); a[x].pb(y);a[y].pb(x); } dep[1]=1; dfs1(1); top[1]=1; dfs2(1); for (int i=2;i<=n;i++) if (w[i]) zkw_ins_single(w[i],v[i]); //for (int i=1;i<=n;i++) printf("%d %d %d %d %d\n",i,fa[i],top[i],w[i],v[i]); scanf("%d",&m); for (int i=1;i<=m;i++){ scanf("%d%d%d",&x,&y,&z); if (x==0){ v[y]=-z; if (w[y]) zkw_ins_single(w[y],v[y]); } else if (x==1){ query(y,z); printf("%d\n",ans); } } }
相关文章推荐
- linux 实现TCP 传输文件。
- Reload the site when reached via browsers back button
- 关于eclipse当中使用SmartUpload使用相对路径的问题
- Shell脚本利用gnuplot绘制图片
- C++学习之路
- HTTP Live Streaming直播(iOS直播)技术分析与实现
- UIProgressView的使用
- Android TextView文字链接4中方法
- 【C++基础02】类中不写成员函数易犯错误模型
- iOS开发技巧(系列十八:扩展UIColor,支持十六进制颜色设置)
- Python小技巧:使用*解包和itertools.product()求笛卡尔积
- Linux Shell脚本实现根据进程名杀死进程
- Mybatis如何关联查询
- CSS实现按钮或文本框圆角效果
- CClientDC CDC CPaintDC CWindowDC 的区别
- Javascript中的substring和substr区别
- android zxing自定义界面,点击按钮开关闪光灯
- Android的TextView中显示不同大小字体的玩法
- 知道某年某月某日,推算当年的第几周?
- 别人分析的Android.