本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!
题目链接:BZOJ3083
正解:树链剖分+线段树+分类讨论
解题报告:
路径修改$+$查询就用链剖资瓷就好了,问题就在于换根操作怎么办。
我们的做法是不真正的换根,而是选择分类讨论。
假设每次的询问点为$x$,当前根为$rt$,如果$rt$在$x$子树中,那么实际的子树就是除了含$rt$的这棵$x$的子树之外的所有部分;
如果$rt$就是$x$,那么子树是全部;
否则的话$x$的子树不会发生变化。
分类讨论一下就做完了==
修改操作用线段树维护,上一个$set$标记就好了。
//It is made by ljh2000 //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。 #include <algorithm> #include <iostream> #include <cstring> #include <vector> #include <cstdio> #include <string> #include <queue> #include <cmath> #include <ctime> #define lc root<<1 #define rc root<<1|1 #define rep(i,j,k) for(int i=j;i<=k;i++) #define reg(i,x) for(int i=first[x];i;i=next[i]) using namespace std; typedef long long LL; const int MAXN = 200011; const int MAXM = 200011; int n,m,rt,ecnt,first[MAXN],to[MAXM],nxt[MAXM],deep[MAXN],top[MAXN],size[MAXN],son[MAXN],father[MAXN],id[MAXN],end[MAXN],pre[MAXN],f[MAXN][18],bel[MAXN]; LL ans,tag[MAXN*3],a[MAXN*3],vv[MAXN]; bool hav[MAXN*3];//!!! inline void link(int x,int y) { nxt[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y; } inline int getint(){ int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w; } inline void pushdown(int root,int l,int r){ if(!hav[root] || l==r)return ; tag[lc]=tag[rc]=a[lc]=a[rc]=tag[root]; hav[lc]=hav[rc]=true; hav[root]=false; tag[root]=0; } inline void build(int root,int l,int r){ if(l==r) { a[root]=vv[ pre[l] ]; return ; } int mid=(l+r)>>1; build(lc,l,mid); build(rc,mid+1,r); a[root]=min(a[lc],a[rc]); } inline void modify(int root,int l,int r,int ql,int qr,LL val){ pushdown(root,l,r); if(ql<=l && r<=qr) { tag[root]=val; hav[root]=true; a[root]=val; return ; } int mid=(l+r)>>1; if(ql<=mid) modify(lc,l,mid,ql,qr,val); if(qr>mid) modify(rc,mid+1,r,ql,qr,val); a[root]=min(a[lc],a[rc]); } inline LL query(int root,int l,int r,int ql,int qr){ pushdown(root,l,r); if(ql<=l && r<=qr) return a[root]; int mid=(l+r)>>1; if(ql>mid) return query(rc,mid+1,r,ql,qr); else if(qr<=mid) return query(lc,l,mid,ql,qr); else return min( query(lc,l,mid,ql,qr) , query(rc,mid+1,r,ql,qr) ); } inline void dfs(int x,int fa){ size[x]=1; for(int i=first[x];i;i=nxt[i]) { int v=to[i]; if(v==fa) continue; deep[v]=deep[x]+1; f[v][0]=x; father[v]=x; dfs(v,x); size[x]+=size[v]; if(size[v]>size[son[x]]) son[x]=v; } } inline void dfs2(int x,int fa){ id[x]=++ecnt; pre[ecnt]=x; if(son[x]) { top[son[x]]=top[x]; dfs2(son[x],x); } for(int i=first[x];i;i=nxt[i]) { int v=to[i]; if(v==fa || v==son[x]) continue; top[v]=v; dfs2(v,x); } end[x]=ecnt; } inline void lca(int x,int y,LL z){ int f1=top[x],f2=top[y]; while(f1!=f2) { if(deep[f1]<deep[f2]) swap(f1,f2),swap(x,y); modify(1,1,n,id[f1],id[x],z); x=father[f1]; f1=top[x]; } if(deep[x]<deep[y]) swap(x,y); modify(1,1,n,id[y],id[x],z); } inline int getF(int x,int F){ for(int i=bel[deep[x]];i>=0;i--) if(deep[f[x][i]]>deep[F]) x=f[x][i]; return x; } inline void work(){ n=getint(); m=getint(); int x,y,type,pos; LL z; for(int i=1;i<n;i++) { x=getint(); y=getint(); link(x,y); link(y,x); } for(int i=1;i<=n;i++) scanf("%lld",&vv[i]); rt=getint(); deep[rt]=1; ecnt=0; dfs(rt,0); top[rt]=rt; dfs2(rt,0); for(int i=2;i<=n;i++) bel[i]=bel[i>>1]+1; for(int j=1;j<=17;j++) for(int i=1;i<=n;i++) f[i][j]=f[f[i][j-1]][j-1]; build(1,1,n); while(m--) { type=getint(); x=getint(); if(type==1) rt=x; else if(type==2) { y=getint(); scanf("%lld",&z); lca(x,y,z); } else { if(x==rt) ans=query(1,1,n,1,n); else if(id[x]<=id[rt] && end[rt]<=end[x]){ ans=1LL<<60; pos=getF(rt,x);//!!! if(id[pos]>1) ans=query(1,1,n,1,id[pos]-1);//!!! if(end[pos]<n) ans=min(ans,query(1,1,n,end[pos]+1,n));//!!! } else ans=query(1,1,n,id[x],end[x]); printf("%lld ",ans); } } } int main() { #ifndef ONLINE_JUDGE freopen("3083.in","r",stdin); freopen("3083.out","w",stdout); #endif work(); return 0; } //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
make:
//It is made by ljh2000 //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。 #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #include <ctime> #include <vector> #include <queue> #include <map> #include <set> #include <string> #include <complex> using namespace std; typedef long long LL; typedef long double LB; typedef complex<double> C; const double pi = acos(-1); inline int getint(){ int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w; } int main() { freopen("3083.in","w",stdout); srand(time(NULL)); int n,m,size,type; n=10; m=10; //n=10000; m=10000; size=10000000; //n=6; m=6; //size=100; printf("%d %d ",n,m); for(int i=2;i<=n;i++) printf("%d %d ",rand()%(i-1)+1,i); for(int i=1;i<=n;i++) printf("%d ",rand()%size+1); printf(" %d ",rand()%n+1); for(int i=1;i<=m;i++) { type=rand()%3+1; printf("%d ",type); if(type==1) { printf("%d ",rand()%n+1); } else if(type==2) { printf("%d %d %d ",rand()%n+1,rand()%n+1,rand()%size+1); } else { printf("%d ",rand()%n+1); } } return 0; } //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
pai:
//It is made by ljh2000 //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。 #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #include <ctime> #include <vector> #include <queue> #include <map> #include <set> #include <string> #include <complex> #include <bitset> using namespace std; typedef long long LL; typedef long double LB; typedef complex<double> C; const double pi = acos(-1); inline int getint(){ int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w; } int main() { int t=0; while(++t) { printf("%d : ",t); system("make.exe"); system("3083.exe"); system("2.exe"); if(system("fc 3083.out 2.out")){ printf("WA "); break; } else printf("AC "); } return 0; } //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
数据:
1.in
10 10 1 2 1 3 1 4 2 5 1 6 4 7 2 8 6 9 7 10 22411 20657 24240 21525 12974 17337 3717 26377 23217 20558 2 2 5 6 15012 3 5 3 9 3 7 1 3 3 10 3 2 2 8 1 29431 1 8 2 7 6 30507
1.out
15012 23217 3717 20558 15012
2.in
6 6 1 2 1 3 1 4 3 5 5 6 38 66 42 98 40 49 6 1 4 3 5 3 3 3 3 3 5 3 5
2.out
40 40 40 40 40