标签:
离线后以宗教为第一关键字,操作时间为第二关键字排序。
<法一>块状树,线下ac,线上tle……
#include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #include<queue> using namespace std; queue<int>q; int f,c; inline void R(int &x){ c=0;f=1; for(;c<‘0‘||c>‘9‘;c=getchar())if(c==‘-‘)f=-1; for(x=0;c>=‘0‘&&c<=‘9‘;c=getchar())(x*=10)+=(c-‘0‘); x*=f; } void P(int x){ if(x<10)putchar(x+‘0‘); else{P(x/10);putchar(x%10+‘0‘);} } #define N 100001 int en,first[N],next[N<<1],v[N<<1]; void AddEdge(const int &U,const int &V) { v[++en]=V; next[en]=first[U]; first[U]=en; } int tops[N],en4; bool delta[N]; struct THING{int op,type,x,y,t,p;}th[N*3]; bool operator < (const THING &a,const THING &b) {return a.type!=b.type ? a.type<b.type : a.t<b.t;} int n,m,w[N],ty[N],en2,en3; int fa[N],dep[N],siz[N],top[N],sz,maxv[N],sumv[N]; int anss[N]; void makeblock() { q.push(1); while(!q.empty()) { int U=q.front(); q.pop(); for(int i=first[U];i;i=next[i]) if(v[i]!=fa[U]) { dep[v[i]]=dep[U]+1; fa[v[i]]=U; if(siz[top[U]]<sz) { ++siz[top[U]]; top[v[i]]=top[U]; } q.push(v[i]); } } } void dfs(int U,int Sumnow,int Maxnow) { maxv[U]=Maxnow; sumv[U]=Sumnow; for(int i=first[U];i;i=next[i]) if(v[i]!=fa[U]&&top[v[i]]==top[U]) dfs(v[i],Sumnow+w[v[i]],max(Maxnow,w[v[i]])); } void dfs0(int U) { maxv[U]=sumv[U]=w[U]=0; for(int i=first[U];i;i=next[i]) if(v[i]!=fa[U]&&top[v[i]]==top[U]) dfs0(v[i]); } void update(const int &p,const int &val) { if(!delta[top[p]]) { dfs0(top[p]); delta[top[p]]=1; } w[p]=val; if(p==top[p]) dfs(p,val,val); else dfs(p,val+sumv[fa[p]],max(val,maxv[fa[p]])); } int Query_max(int U,int V) { int res=0; while(U!=V) { if(top[U]==top[V]) { if(dep[U]<dep[V]) swap(U,V); res=max(res,delta[top[U]]?w[U]:0); U=fa[U]; } else { if(dep[top[U]]<dep[top[V]]) swap(U,V); res=max(res,delta[top[U]]?maxv[U]:0); U=fa[top[U]]; } } return max(res,delta[top[U]]?w[U]:0); } int Query_sum(int U,int V) { int res=0; while(U!=V) { if(top[U]==top[V]) { if(dep[U]<dep[V]) swap(U,V); res+=(delta[top[U]]?w[U]:0); U=fa[U]; } else { if(dep[top[U]]<dep[top[V]]) swap(U,V); res+=(delta[top[U]]?sumv[U]:0); U=fa[top[U]]; } } return res+(delta[top[U]]?w[U]:0); } int main() { int A,B; char op[3]; R(n); R(m); for(int i=1;i<=n;++i) { R(w[i]); R(ty[i]); th[i].type=ty[i]; th[i].x=i; th[i].t=i; th[i].y=w[i]; } for(int i=1;i<n;++i) { R(A); R(B); AddEdge(A,B); AddEdge(B,A); } sz=sqrt(0.03*(double)n); for(int i=1;i<=n;i++) { top[i]=i; siz[i]=1; } makeblock(); en2=n; for(int i=1;i<=m;++i) { op[0]=getchar(); op[1]=getchar(); R(A); R(B); if(op[0]==‘C‘&&op[1]==‘C‘) { th[++en2].type=ty[A]; th[en2].x=A; th[en2].y=0; th[en2].t=en2; ty[A]=B; th[++en2].type=ty[A]; th[en2].x=A; th[en2].y=w[A]; th[en2].t=en2; } else if(op[0]==‘C‘&&op[1]==‘W‘) { w[A]=B; th[++en2].type=ty[A]; th[en2].x=A; th[en2].y=w[A]; th[en2].t=en2; } else if(op[0]==‘Q‘&&op[1]==‘S‘) { th[++en2].op=1; th[en2].type=ty[A]; th[en2].x=A; th[en2].y=B; th[en2].t=en2; th[en2].p=++en3; } else { th[++en2].op=2; th[en2].type=ty[A]; th[en2].x=A; th[en2].y=B; th[en2].t=en2; th[en2].p=++en3; } } sort(th+1,th+en2+1); memset(w,0,sizeof(w)); for(int i=1;i<=n;i++) if(top[i]==i) tops[++en4]=i; for(int i=1;i<=en4;++i) delta[tops[i]]=1; for(int i=1;i<=en2;++i) { if(th[i].type!=th[i-1].type&&i!=1) for(int j=1;j<=en4;++j) delta[tops[j]]=0; if(!th[i].op) update(th[i].x,th[i].y); else if(th[i].op==1) anss[th[i].p]=Query_sum(th[i].x,th[i].y); else anss[th[i].p]=Query_max(th[i].x,th[i].y); } for(int i=1;i<=en3;++i) P(anss[i]),puts(""); return 0; }
<法二>树链剖分+线段树
#include<cstdio> #include<algorithm> using namespace std; #define lson rt<<1,l,m #define rson rt<<1|1,m+1,r int f,c; inline void R(int &x){ c=0;f=1; for(;c<‘0‘||c>‘9‘;c=getchar())if(c==‘-‘)f=-1; for(x=0;c>=‘0‘&&c<=‘9‘;c=getchar())(x*=10)+=(c-‘0‘); x*=f; } void P(int x){ if(x<10)putchar(x+‘0‘); else{P(x/10);putchar(x%10+‘0‘);} } #define N 100001 int en,first[N],next[N<<1],v[N<<1]; void AddEdge(const int &U,const int &V) { v[++en]=V; next[en]=first[U]; first[U]=en; } struct THING{int op,type,x,y,t,p;}th[N*3]; bool operator < (const THING &a,const THING &b) {return a.type!=b.type ? a.type<b.type : a.t<b.t;} int n,m,w[N],ty[N],en2,en3; int anss[N]; int dep[N],siz[N],fa[N],son[N],top[N],Num[N],tot; void dfs(int U,int d) { dep[U]=d; siz[U]=1; for(int i=first[U];i;i=next[i]) if(v[i]!=fa[U]) { fa[v[i]]=U; dfs(v[i],d+1); siz[U]+=siz[v[i]]; if(siz[v[i]]>siz[son[U]]) son[U]=v[i]; } } void dfs2(int U) { if(son[U]) { top[son[U]]=top[U]; Num[son[U]]=++tot; dfs2(son[U]); } for(int i=first[U];i;i=next[i]) if(v[i]!=fa[U]&&v[i]!=son[U]) { top[v[i]]=v[i]; Num[v[i]]=++tot; dfs2(v[i]); } } int maxv[N<<2],sumv[N<<2]; bool delta[N<<2]; void pushdown(const int &rt) { if(delta[rt]) { delta[rt<<1]=delta[rt<<1|1]=1; maxv[rt<<1]=maxv[rt<<1|1]=sumv[rt<<1]=sumv[rt<<1|1]=0; delta[rt]=0; } } void update(int p,int v,int rt,int l,int r) { if(l==r) { maxv[rt]=sumv[rt]=v; return; } pushdown(rt); int m=(l+r>>1); if(p<=m) update(p,v,lson); else update(p,v,rson); sumv[rt]=sumv[rt<<1]+sumv[rt<<1|1]; maxv[rt]=max(maxv[rt<<1],maxv[rt<<1|1]); } int query1(int ql,int qr,int rt,int l,int r) { if(ql<=l&&r<=qr) return sumv[rt]; pushdown(rt); int m=(l+r>>1),res=0; if(ql<=m) res+=query1(ql,qr,lson); if(m<qr) res+=query1(ql,qr,rson); return res; } int query2(int ql,int qr,int rt,int l,int r) { if(ql<=l&&r<=qr) return maxv[rt]; pushdown(rt); int m=(l+r>>1),res=0; if(ql<=m) res=max(res,query2(ql,qr,lson)); if(m<qr) res=max(res,query2(ql,qr,rson)); return res; } int Query1(int U,int V) { int f1=top[U],f2=top[V],res=0; while(f1!=f2) { if(dep[f1]<dep[f2]) { swap(U,V); swap(f1,f2); } res+=query1(Num[f1],Num[U],1,1,n); U=fa[f1]; f1=top[U]; } if(dep[U]>dep[V]) swap(U,V); return res+query1(Num[U],Num[V],1,1,n); } int Query2(int U,int V) { int f1=top[U],f2=top[V],res=0; while(f1!=f2) { if(dep[f1]<dep[f2]) { swap(U,V); swap(f1,f2); } res=max(res,query2(Num[f1],Num[U],1,1,n)); U=fa[f1]; f1=top[U]; } if(dep[U]>dep[V]) swap(U,V); return max(res,query2(Num[U],Num[V],1,1,n)); } int main() { int A,B; char op[3]; R(n); R(m); for(int i=1;i<=n;++i) { R(w[i]); R(ty[i]); th[i].type=ty[i]; th[i].x=i; th[i].t=i; th[i].y=w[i]; } for(int i=1;i<n;++i) { R(A); R(B); AddEdge(A,B); AddEdge(B,A); } top[1]=1; Num[1]=++tot; dfs(1,1); dfs2(1); en2=n; for(int i=1;i<=m;++i) { op[0]=getchar(); op[1]=getchar(); R(A); R(B); if(op[0]==‘C‘&&op[1]==‘C‘) { th[++en2].type=ty[A]; th[en2].x=A; th[en2].y=0; th[en2].t=en2; ty[A]=B; th[++en2].type=ty[A]; th[en2].x=A; th[en2].y=w[A]; th[en2].t=en2; } else if(op[0]==‘C‘&&op[1]==‘W‘) { w[A]=B; th[++en2].type=ty[A]; th[en2].x=A; th[en2].y=w[A]; th[en2].t=en2; } else if(op[0]==‘Q‘&&op[1]==‘S‘) { th[++en2].op=1; th[en2].type=ty[A]; th[en2].x=A; th[en2].y=B; th[en2].t=en2; th[en2].p=++en3; } else { th[++en2].op=2; th[en2].type=ty[A]; th[en2].x=A; th[en2].y=B; th[en2].t=en2; th[en2].p=++en3; } } sort(th+1,th+en2+1); for(int i=1;i<=en2;++i) { if(th[i].type!=th[i-1].type&&i!=1) delta[1]=1; if(!th[i].op) update(Num[th[i].x],th[i].y,1,1,n); else if(th[i].op==1) anss[th[i].p]=Query1(th[i].x,th[i].y); else anss[th[i].p]=Query2(th[i].x,th[i].y); } for(int i=1;i<=en3;++i) P(anss[i]),puts(""); return 0; }
【块状树】【树链剖分】【线段树】bzoj3531 [Sdoi2014]旅行
标签:
原文地址:http://www.cnblogs.com/autsky-jadek/p/4322678.html