bzoj3531: [Sdoi2014]旅行
2016-08-12 20:55
393 查看
链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3531
题意:中文题。
分析:如果没有颜色的干扰,那么这题只是一个裸树链剖分,但是有了颜色,而且颜色数还多。我们可以想象一下,我们对于每一种颜色都单独取出它们来,然后将相同的颜色像树链剖分那样建线段树,但是如果我们像普通的那样建显然空间会爆炸,我们可以像主席树一样只建有效节点,这样的话我们最多要在线段树中建出2*10^5个叶子,也就是说2*10^5*logn个节点就行啦,然后每次询问就到对应的颜色的那颗线段树上去查询即可。时间O(nlognlogn)空间(n+q)*logn。
代码:
#include<map> #include<set> #include<cmath> #include<queue> #include<bitset> #include<math.h> #include<vector> #include<string> #include<stdio.h> #include<cstring> #include<iostream> #include<algorithm> #pragma comment(linker, "/STACK:102400000,102400000") using namespace std; const int N=100010; const int mod=100000000; const int MOD1=1000000007; const int MOD2=1000000009; const double EPS=0.00000001; typedef long long ll; const ll MOD=1000000007; const int INF=1000000010; const ll MAX=1000000000; const double pi=acos(-1.0); typedef double db; typedef unsigned long long ull; struct node { int l,r,ls,rs,mx,sum; node(){} node(int l,int r,int ls,int rs,int mx,int sum):l(l),r(r),ls(ls),rs(rs),mx(mx),sum(sum) {} }tr[50*N]; int tot,u ,v[2*N],pre[2*N]; void add(int x,int y) { v[tot]=y;pre[tot]=u[x];u[x]=tot++; v[tot]=x;pre[tot]=u[y];u[y]=tot++; } char s[5]; int n,w ,c ,col ; int fa ,dep ,siz ,son ,top ,pos ; void dfs1(int x,int y) { siz[x]=1;son[x]=0; fa[x]=y;dep[x]=dep[y]+1; int i,mx=0; for (i=u[x];i!=-1;i=pre[i]) if (v[i]!=y) { dfs1(v[i],x);siz[x]+=siz[v[i]]; if (siz[v[i]]>mx) son[x]=v[i],mx=siz[v[i]]; } } void dfs2(int x,int y) { if (son[y]==x) top[x]=top[y]; else top[x]=x;pos[x]=++tot; if (son[x]) dfs2(son[x],x); for (int i=u[x];i!=-1;i=pre[i]) if (v[i]!=y&&v[i]!=son[x]) dfs2(v[i],x); } void updata(int x,int po,int ww) { if (tr[x].l==tr[x].r) { tr[x].sum=tr[x].mx=ww;return ; } int mid=(tr[x].l+tr[x].r)>>1; if (po<=mid) { if (!tr[x].ls) { tot++;tr[tot]=node(tr[x].l,mid,0,0,0,0),tr[x].ls=tot; } updata(tr[x].ls,po,ww); } else { if (!tr[x].rs) { tot++;tr[tot]=node(mid+1,tr[x].r,0,0,0,0),tr[x].rs=tot; } updata(tr[x].rs,po,ww); } tr[x].mx=max(tr[tr[x].ls].mx,tr[tr[x].rs].mx); tr[x].sum=tr[tr[x].ls].sum+tr[tr[x].rs].sum; } void change(int co,int po,int ww) { if (!col[co]) { tr[++tot]=node(1,n,0,0,0,0);col[co]=tot; } updata(col[co],po,ww); } int statsum(int x,int L,int R) { if (x==0||(tr[x].l==L&&tr[x].r==R)) return tr[x].sum; int mid=(tr[x].l+tr[x].r)>>1; if (R<=mid) return statsum(tr[x].ls,L,R); else if (L>mid) return statsum(tr[x].rs,L,R); else return statsum(tr[x].ls,L,mid)+statsum(tr[x].rs,mid+1,R); } int statmax(int x,int L,int R) { if (x==0||(tr[x].l==L&&tr[x].r==R)) return tr[x].mx; int mid=(tr[x].l+tr[x].r)>>1; if (R<=mid) return statmax(tr[x].ls,L,R); else if (L>mid) return statmax(tr[x].rs,L,R); else return max(statmax(tr[x].ls,L,mid),statmax(tr[x].rs,mid+1,R)); } int getsum(int co,int x,int y) { int ret=0,f1=top[x],f2=top[y]; while (f1!=f2) { if (dep[f1]<dep[f2]) swap(x,y),swap(f1,f2); ret+=statsum(co,pos[f1],pos[x]); x=fa[f1];f1=top[x]; } if (dep[x]<dep[y]) swap(x,y); ret+=statsum(co,pos[y],pos[x]); return ret; } int getmax(int co,int x,int y) { int ret=0,f1=top[x],f2=top[y]; while (f1!=f2) { if (dep[f1]<dep[f2]) swap(x,y),swap(f1,f2); ret=max(ret,statmax(co,pos[f1],pos[x])); x=fa[f1];f1=top[x]; } if (dep[x]<dep[y]) swap(x,y); ret=max(ret,statmax(co,pos[y],pos[x])); return ret; } int main() { int i,q,x,y; scanf("%d%d", &n, &q); tot=0;memset(u,-1,sizeof(u)); for (i=1;i<=n;i++) scanf("%d%d", &w[i], &c[i]); for (i=1;i<n;i++) scanf("%d%d", &x, &y),add(x,y); tr[0]=node(0,0,0,0,0,0); dfs1(1,0);tot=0;dfs2(1,0); for (tot=0,i=1;i<=n;i++) change(c[i],pos[i],w[i]); while (q--) { scanf("%s%d%d", s, &x, &y); if (s[1]=='C') { change(c[x],pos[x],0);c[x]=y;change(c[x],pos[x],w[x]); } else if (s[1]=='W') { change(c[x],pos[x],0);w[x]=y;change(c[x],pos[x],w[x]); } else if (s[1]=='S') printf("%d\n", getsum(col[c[x]],x,y)); else printf("%d\n", getmax(col[c[x]],x,y)); } return 0; }
相关文章推荐
- Bzoj3531:[Sdoi2014]旅行:树链剖分+动态开点线段树
- BZOJ3531: [Sdoi2014]旅行
- BZOJ3531: [Sdoi2014]旅行
- bzoj3531: [Sdoi2014]旅行
- Bzoj3531: [Sdoi2014]旅行
- BZOJ3531 [Sdoi2014]旅行 【树剖 + 线段树】
- bzoj3531: [Sdoi2014]旅行
- [Sdoi 2014] bzoj3531 旅行 [树链剖分]
- bzoj3531 [Sdoi2014]旅行 树链剖分 线段树
- BZOJ3531 【Sdoi2014】旅行
- bzoj3531[Sdoi2014]旅行
- BZOJ3531 [Sdoi2014]旅行
- BZOJ3531 [Sdoi2014]旅行
- BZOJ3531 [Sdoi2014]旅行——树剖+动态开点线段树
- bzoj3531【SDOI2014】旅行
- bzoj3531 [Sdoi2014]旅行(树链剖分+动态开点线段树)
- bzoj3531 [Sdoi2014]旅行
- bzoj3531 [Sdoi2014]旅行 【树链剖分+线段树动态开点】
- bzoj3531 [Sdoi2014]旅行 树链剖分+动态开线段树
- 【BZOJ3531】旅行(SDOI2014)-树链剖分+动态加点线段树