bzoj2157 旅游 树链剖分
2017-04-15 21:39
399 查看
4000
其实就是个树链剖分,但是变成了边权而已,把边权移到他深度更大的端点上就行了。问题是操作太多了,而且还有个改变权值和取反我还要单独拉出来打。。打了半个小时,,编译调了半天,6000多B,都不想肉眼检查结果1A了。。有点窃喜。。
注意取反哪里的最大最小值的维护,要倒过来。
其实就是个树链剖分,但是变成了边权而已,把边权移到他深度更大的端点上就行了。问题是操作太多了,而且还有个改变权值和取反我还要单独拉出来打。。打了半个小时,,编译调了半天,6000多B,都不想肉眼检查结果1A了。。有点窃喜。。
注意取反哪里的最大最小值的维护,要倒过来。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define fo(i,a,b) for(int i=a;i<=b;i++) #define fd(i,a,b) for(int i=a;i>=b;i--) using namespace std; const int N=5e5+5; const int inf=2147483646; int head ,next ,go ,val ,n; int size ,son ,dep ,pos ,fa ,a ,top ; int tim,tot; struct node { int l,r,sum,mx,mn,lazy; }t ; inline void add(int x,int y,int z) { go[++tot]=y; next[tot]=head[x]; val[tot]=z; head[x]=tot; } inline void dfs(int x) { size[x]=1; for(int i=head[x];i;i=next[i]) { int v=go[i]; if (v!=fa[x]) { a[v]=val[i]; dep[v]=dep[x]+1; fa[v]=x; dfs(v); size[x]+=size[v]; } } } inline void dfs1(int x,int chain) { int k=0; pos[x]=++tim; top[x]=chain; for(int i=head[x];i;i=next[i]) { int v=go[i]; if (v!=fa[x]) { if (size[v]>size[k])k=v; } } if (!k)return; son[x]=k; dfs1(k,chain); for(int i=head[x];i;i=next[i]) { int v=go[i]; if (v!=fa[x]&&v!=son[x]) { dfs1(v,v); } } } inline void build(int x,int l,int r) { t[x].l=l,t[x].r=r; if (l==r)return; int mid=(l+r)>>1; build(x<<1,l,mid); build(x<<1|1,mid+1,r); } void pushlazy(int d) { if (t[d].lazy==0||t[d].l==t[d].r) return; t[d*2].lazy=1-t[d*2].lazy; t[d*2+1].lazy=1-t[d*2+1].lazy; t[d].lazy=0; t[d*2].sum=-t[d*2].sum; int w=t[d*2].mn;t[d*2].mn=-t[d*2].mx;t[d*2].mx=-w; t[d*2+1].sum=-t[d*2+1].sum; w=t[d*2+1].mn;t[d*2+1].mn=-t[d*2+1].mx;t[d*2+1].mx=-w; } void change(int d,int x,int y) { pushlazy(d); if (t[d].l==t[d].r) { if (x==1) { t[d].mn=inf; t[d].mx=-inf; t[d].sum=0; }else t[d].mn=t[d].mx=t[d].sum=y; return; } int mid=(t[d].l+t[d].r)/2; if (x<=mid) change(d*2,x,y); else change(d*2+1,x,y); t[d].mn=min(t[d*2].mn,t[d*2+1].mn); t[d].mx=max(t[d*2].mx,t[d*2+1].mx); t[d].sum=t[d*2].sum+t[d*2+1].sum; } void queryoppo(int d,int x,int y) { pushlazy(d); if (t[d].l==x&&t[d].r==y) { t[d].sum=-t[d].sum; int w=t[d].mn;t[d].mn=-t[d].mx;t[d].mx=-w; t[d].lazy=1; return; } int mid=(t[d].l+t[d].r)/2; if (y<=mid) queryoppo(d*2,x,y); else if (x>mid) queryoppo(d*2+1,x,y); else { queryoppo(d*2,x,mid); queryoppo(d*2+1,mid+1,y); } t[d].mn=min(t[d*2].mn,t[d*2+1].mn); t[d].mx=max(t[d*2].mx,t[d*2+1].mx); t[d].sum=t[d*2].sum+t[d*2+1].sum; } void solveoppo(int x,int y) { while (top[x]!=top[y]) { if (dep[top[x]]<dep[top[y]]) swap(x,y); queryoppo(1,pos[top[x]],pos[x]); x=fa[top[x]]; } if (x==y) return; if (dep[x]>dep[y]) swap(x,y); x=son[x]; queryoppo(1,pos[x],pos[y]); } int querysum(int d,int x,int y) { pushlazy(d); if (t[d].l==x&&t[d].r==y) return t[d].sum; int mid=(t[d].l+t[d].r)/2; if (y<=mid) return querysum(d*2,x,y); else if (x>mid) return querysum(d*2+1,x,y); else return querysum(d*2,x,mid)+querysum(d*2+1,mid+1,y); } int solvesum(int x,int y) { int sum=0; while (top[x]!=top[y]) { if (dep[top[x]]<dep[top[y]]) swap(x,y); sum+=querysum(1,pos[top[x]],pos[x]); x=fa[top[x]]; } if (x==y) return sum; if (dep[x]>dep[y]) swap(x,y); x=son[x]; sum+=querysum(1,pos[x],pos[y]); return sum; } int querymin(int d,int x,int y) { pushlazy(d); if (t[d].l==x&&t[d].r==y) return t[d].mn; int mid=(t[d].l+t[d].r)/2; if (y<=mid) return querymin(d*2,x,y); else if (x>mid) return querymin(d*2+1,x,y); else return min(querymin(d*2,x,mid),querymin(d*2+1,mid+1,y)); } int solvemin(int x,int y) { int mn=inf; while (top[x]!=top[y]) { if (dep[top[x]]<dep[top[y]]) swap(x,y); mn=min(mn,querymin(1,pos[top[x]],pos[x])); x=fa[top[x]]; } if (x==y) return mn; if (dep[x]>dep[y]) swap(x,y); x=son[x]; mn=min(mn,querymin(1,pos[x],pos[y])); return mn; } int querymax(int d,int x,int y) { pushlazy(d); if (t[d].l==x&&t[d].r==y) return t[d].mx; int mid=(t[d].l+t[d].r)/2; if (y<=mid) return querymax(d*2,x,y); else if (x>mid) return querymax(d*2+1,x,y); else return max(querymax(d*2,x,mid),querymax(d*2+1,mid+1,y)); } int solvemax(int x,int y) { int mx=-inf; while (top[x]!=top[y]) { if (dep[top[x]]<dep[top[y]]) swap(x,y); mx=max(querymax(1,pos[top[x]],pos[x]),mx); x=fa[top[x]]; } if (x==y) return mx; if (dep[x]>dep[y]) swap(x,y); x=son[x]; mx=max(mx,querymax(1,pos[x],pos[y])); return mx; } int main() { scanf("%d",&n); fo(i,1,n-1) { int x,y,z; scanf("%d%d%d",&x,&y,&z); x++,y++; add(x,y,z); add(y,x,z); } dfs(1); dfs1(1,0); build(1,1,n); fo(i,1,n)change(1,pos[i],a[i]); int q; scanf("%d",&q); fo(i,1,q) { char ch[10]; int x,y; scanf("%s%d%d",ch,&x,&y); if (ch[0]!='C') { x++,y++; } if (ch[0]=='C') if(dep[go[x*2-1]]>dep[go[x*2]])change(1,pos[go[x*2-1]],y); else change(1,pos[go[x*2]],y); else if (ch[0]=='N')solveoppo(x,y); else { if (ch[0]=='S')printf("%d\n",solvesum(x,y)); else if (ch[1]=='I')printf("%d\n",solvemin(x,y)); else printf("%d\n",solvemax(x,y)); } } }
相关文章推荐
- [BZOJ2157] 旅游 树链剖分
- BZOJ 2157 旅游 树链剖分
- 【BZOJ2157】旅游(树链剖分,Link-Cut Tree)
- BZOJ 2157: 旅游 树链剖分
- BZOJ 2157: 旅游 树链剖分
- [bzoj2157][树链剖分]旅游
- bzoj2157 旅游(树链剖分)
- 【树链剖分】【bzoj2157】: 旅游
- 【BZOJ2157】旅游,树链剖分练习
- BZOJ[2157]旅游 树链剖分+线段树
- BZOJ 2157 旅游 树链剖分
- bzoj 2157: 旅游【树链剖分+线段树】
- 【树链剖分】【线段树】bzoj2157 旅游
- [动态树 LCT] BZOJ 2157 旅游
- 【BZOJ2157】旅游
- [BZOJ2157] 旅游 边权树链剖分
- bzoj 3999: [TJOI2015]旅游(树链剖分)
- [BZOJ2157]旅游
- 【BZOJ】2157: 旅游
- [BZOJ2049]洞穴勘测[BZOJ2157]旅游Link-Cut Tree模板题