BZOJ 2157: 旅游 树链剖分
Fancy
posted @ 2015年7月04日 21:44
in BZOJ
, 480 阅读
题目大意:更改桥上的愉悦度,求路径上的最大、最小、总愉悦度。
看完数据我疯了。。。自己造了个小数据。。。
维护边权的树链剖分,边的编号为下面一个点的编号
注意点是从0开始,所以我把点都加1了,其实直接写应该也可以
Min Max Sum函数中如果x和y相等的话要返回inf -inf 0,才开始没写,改了好长时间。。。
#include<iostream> #include<cstdio> #include<vector> using namespace std; const int inf=20000001; const int N=20010; struct abcd { int a,b,c; } v[N]; struct TREE { int lc,rc,l,r,sum,max,min; } tree[N*4]; vector<int> to[N*2]; char s[4]; int n,m,totw,tot=1; int vis[N],dep[N],fa[N],son[N],siz[N],top[N],w[N],val[N]; void DFS(int x) { int t=0; vis[x]=1;dep[x]=dep[fa[x]]+1; for(int i=0;i<to[x].size();i++) { int y=to[x][i]; if(!vis[y]) { t=1; fa[y]=x;DFS(y);siz[x]+=siz[y]; if(siz[y]>siz[son[x]]) son[x]=y; } } } void DFS2(int x) { if(son[x]) { top[son[x]]=top[x]; w[son[x]]=++totw; DFS2(son[x]); } for(int i=0;i<to[x].size();i++) { int y=to[x][i]; if(y!=fa[x]&&y!=son[x]) { top[y]=y; w[y]=++totw; DFS2(y); } } } void build(int x,int l,int r) { tree[x].l=l;tree[x].r=r; if(r==l) { tree[x].sum=val[l];tree[x].max=val[l];tree[x].min=val[l]; return; } int mid=(l+r)/2; tree[x].lc=++tot; build(tree[x].lc,l,mid); tree[x].rc=++tot; build(tree[x].rc,mid+1,r); tree[x].sum=tree[tree[x].lc].sum+tree[tree[x].rc].sum; tree[x].max=max(tree[tree[x].lc].max,tree[tree[x].rc].max); tree[x].min=min(tree[tree[x].lc].min,tree[tree[x].rc].min); } void change(int x,int v,int d) { if(tree[x].l==tree[x].r) { tree[x].sum=d;tree[x].max=d;tree[x].min=d; return; } int mid=(tree[x].l+tree[x].r)/2; if(v<=mid) change(tree[x].lc,v,d); else change(tree[x].rc,v,d); tree[x].sum=tree[tree[x].lc].sum+tree[tree[x].rc].sum; tree[x].max=max(tree[tree[x].lc].max,tree[tree[x].rc].max); tree[x].min=min(tree[tree[x].lc].min,tree[tree[x].rc].min); } void changefan(int x,int v) { if(tree[x].l==tree[x].r) { int d=-tree[x].sum; tree[x].sum=d;tree[x].max=d;tree[x].min=d; return; } int mid=(tree[x].l+tree[x].r)/2; if(v<=mid) changefan(tree[x].lc,v); else changefan(tree[x].rc,v); tree[x].sum=tree[tree[x].lc].sum+tree[tree[x].rc].sum; tree[x].max=max(tree[tree[x].lc].max,tree[tree[x].rc].max); tree[x].min=min(tree[tree[x].lc].min,tree[tree[x].rc].min); } void Fan(int x,int y) { int f1=top[x],f2=top[y]; if(f1!=f2) { if(dep[f1]<dep[f2]) swap(x,y),swap(f1,f2); while(x!=fa[f1]) changefan(1,w[x]),x=fa[x]; return Fan(fa[f1],y); } else { if(dep[x]<dep[y]) swap(x,y); while(x!=y) changefan(1,w[x]),x=fa[x]; } } int querysum(int x,int l,int r) { if(l>r) swap(l,r); if(l<=tree[x].l&&tree[x].r<=r) return tree[x].sum; int mid=(tree[x].l+tree[x].r)/2; int ans=0; if(l<=mid) ans+=querysum(tree[x].lc,l,r); if(mid<r) ans+=querysum(tree[x].rc,l,r); return ans; } int Sum(int x,int y) { if(x==y) return 0; int f1=top[x],f2=top[y]; if(f1!=f2) { if(dep[f1]<dep[f2]) swap(x,y),swap(f1,f2); return querysum(1,w[f1],w[x])+Sum(fa[f1],y); } else { if(x>y) swap(x,y); return querysum(1,w[x]+1,w[y]); } } int querymax(int x,int l,int r) { if(l>r) swap(l,r); if(l<=tree[x].l&&tree[x].r<=r) return tree[x].max; int mid=(tree[x].l+tree[x].r)/2; int ans=-inf; if(l<=mid) ans=max(ans,querymax(tree[x].lc,l,r)); if(mid<r) ans=max(ans,querymax(tree[x].rc,l,r)); return ans; } int Max(int x,int y) { if(x==y) return -inf; int f1=top[x],f2=top[y]; if(f1!=f2) { if(dep[f1]<dep[f2]) swap(x,y),swap(f1,f2); return max(querymax(1,w[f1],w[x]),Max(fa[f1],y)); } else { if(x>y) swap(x,y); return querymax(1,w[x]+1,w[y]); } } int querymin(int x,int l,int r) { if(l>r) swap(l,r); if(l<=tree[x].l&&tree[x].r<=r) return tree[x].min; int mid=(tree[x].l+tree[x].r)/2; int ans=inf; if(l<=mid) ans=min(ans,querymin(tree[x].lc,l,r)); if(mid<r) ans=min(ans,querymin(tree[x].rc,l,r)); return ans; } int Min(int x,int y) { if(x==y) return inf; int f1=top[x],f2=top[y]; if(f1!=f2) { if(dep[f1]<dep[f2]) swap(x,y),swap(f1,f2); return min(querymin(1,w[f1],w[x]),Min(fa[f1],y)); } else { if(x>y) swap(x,y); return querymin(1,w[x]+1,w[y]); } } int main() { scanf("%d",&n); for(int i=1;i<n;i++) { scanf("%d%d%d",&v[i].a,&v[i].b,&v[i].c); v[i].a++;v[i].b++; to[v[i].a].push_back(v[i].b); to[v[i].b].push_back(v[i].a); } for(int i=1;i<=n;i++) siz[i]=1; DFS(1); top[1]=1;DFS2(1); for(int i=1;i<n;i++) { if(v[i].a<v[i].b) swap(v[i].a,v[i].b); val[w[v[i].a]]=v[i].c; } build(1,1,n-1); scanf("%d",&m); for(int i=1,x,y;i<=m;i++) { scanf("%s",s); scanf("%d%d",&x,&y); if(s[0]=='C') change(1,w[v[x].a],y); else if(s[0]=='N') Fan(x+1,y+1); else if(s[0]=='S') printf("%d\n",Sum(x+1,y+1)); else if(s[0]=='M'&&s[1]=='A') printf("%d\n",Max(x+1,y+1)); else printf("%d\n",Min(x+1,y+1)); } }