【bzoj3531】[SDOI2014]旅行
来源:互联网 发布:2011年网络春晚 编辑:程序博客网 时间:2024/05/10 08:22
裸树剖+动态开点线段树.
第一次写动态开点线段树,感觉写了主席树的build+普通线段树的query,其实蛮简单的,以前钊神推荐过,有机会还是多写写.
#include<cstdio>#include<iostream>#include<cstring>#include<string>#include<algorithm>using namespace std;const int N=100010;char s[3];int qx,n,m,te,sz,q,tot;int num[N],size[N],tree[N],val[N],w[N],c[N];int head[N],son[N],fa[N],h[N],tp[N],root[N];struct edge{ int v,next;}e[200010];struct seg{ int sum,mx; int l,r,lch,rch;}tr[2000010];inline int F(){ register int aa,bb;register char ch; while(ch=getchar(),(ch<'0'||ch>'9')&&ch!='-');ch=='-'?aa=bb=0:(aa=ch-'0',bb=1); while(ch=getchar(),ch>='0'&&ch<='9')aa=(aa<<3)+(aa<<1)+ch-'0';return bb?aa:-aa;}void add(int u,int v){ e[++te].v=v; e[te].next=head[u]; head[u]=te;}void dfs1(int x){ size[x]=1; for (int i=head[x];i;i=e[i].next) { int v=e[i].v; if (v==fa[x])continue; fa[v]=x; h[v]=h[x]+1; dfs1(v); size[x]+=size[v]; if (size[v]>size[son[x]])son[x]=v; }}void dfs2(int x,int chain){ tp[x]=chain; num[x]=++sz; if (!son[x])return; dfs2(son[x],chain); for (int i=head[x];i;i=e[i].next) { int v=e[i].v; if (v==fa[x]||v==son[x])continue; dfs2(v,v); }}void updata(int k){ tr[k].sum=tr[tr[k].lch].sum+tr[tr[k].rch].sum; tr[k].mx=max(tr[tr[k].lch].mx,tr[tr[k].rch].mx);}void build(int &k,int l,int r,int x,int v){ int mid=(l+r)>>1; if(!k)k=++tot; tr[k].l=l,tr[k].r=r; if (l==r) { tr[k].sum=v; tr[k].mx=v; return; } if (x<=mid)build(tr[k].lch,l,mid,x,v); else build(tr[k].rch,mid+1,r,x,v); updata(k); }void querysum(int k,int x,int y){ int l=tr[k].l,r=tr[k].r; if (!k)return; if (x<=l&&r<=y) { qx+=tr[k].sum; return; } int mid=(l+r)>>1; if (x<=mid)querysum(tr[k].lch,x,y); if (y>mid)querysum(tr[k].rch,x,y);}void querymax(int k,int x,int y){ int l=tr[k].l,r=tr[k].r; if (!k)return; if (x<=l&&r<=y) { qx=max(qx,tr[k].mx); return; } int mid=(l+r)>>1;// getchar();// cout<<k<<' '<<x<<' '<<y<<' '<<l<<' '<<r<<' '<<mid<<endl; if (x<=mid)querymax(tr[k].lch,x,y); if (y>mid)querymax(tr[k].rch,x,y);}int solvesum(int x,int y,int st){ qx=0; while(tp[x]!=tp[y]) { if (h[tp[x]]<h[tp[y]])swap(x,y); querysum(root[st],num[tp[x]],num[x]); x=fa[tp[x]]; } if (num[x]>num[y])swap(x,y); querysum(root[st],num[x],num[y]); return qx;}int solvemax(int x,int y,int st){ qx=0; while(tp[x]!=tp[y]) { if (h[tp[x]]<h[tp[y]])swap(x,y);// cout<<111111111<<endl; querymax(root[st],num[tp[x]],num[x]); x=fa[tp[x]]; } if (num[x]>num[y])swap(x,y);// cout<<22222222<<endl; querymax(root[st],num[x],num[y]); return qx;}int main(){ int u,v,x,C,y; n=F(),q=F(); for(int i=1;i<=n;++i) w[i]=F(),c[i]=F(); for (int i=1;i<n;++i) u=F(),v=F(),add(u,v),add(v,u); h[1]=1;dfs1(1);dfs2(1,1); for (int i=1;i<=n;++i) build(root[c[i]],1,n,num[i],w[i]); for (int i=1;i<=q;++i) { scanf("%s",s);x=F(),y=F(); if (s[0]=='C'&&s[1]=='C') { build(root[c[x]],1,n,num[x],0); build(root[y],1,n,num[x],w[x]); c[x]=y; } else if (s[0]=='C'&&s[1]=='W') { build(root[c[x]],1,n,num[x],y); w[x]=y; } else if (s[0]=='Q'&&s[1]=='S') printf("%d\n",solvesum(x,y,c[x])); else if (s[0]=='Q'&&s[1]=='M') printf("%d\n",solvemax(x,y,c[x])); }}
0 0
- BZOJ3531 [Sdoi2014]旅行
- 【BZOJ3531】【Sdoi2014】旅行 树链剖分。
- [BZOJ3531]SDOI2014旅行
- 【SDOI2014】【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]旅行(树剖)
- bzoj3531: [Sdoi2014]旅行
- bzoj3531: [Sdoi2014]旅行
- leetcode
- rocketmq,IBM mq,kafka ,rabbitmq
- 学习Layout总结
- 字符串面试题
- PAT算法笔记(四)————锤子剪刀布
- 【bzoj3531】[SDOI2014]旅行
- android 获取HOME组件的Activity信息
- c语言实现通讯录(动态内存开辟)
- 抢救DB2数据之终极工具:db2dart
- 前端clearfix的理解
- MySQL安装配置,命令,异常纪要
- 栈与队列
- js中取json对象的键和值以及取数组的索引和值
- 装Vmware的体会