[BZOJ1036][JZOJ2256]【ZJOI2008】树的统计(树链剖分模板)
来源:互联网 发布:js date format 函数 编辑:程序博客网 时间:2024/06/06 03:25
Description
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。
我们将以下面的形式来要求你对这棵树完成一些操作:
I. CHANGE u t : 把结点u的权值改为t
II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值
III. QSUM u v: 询问从点u到点v的路径上的节点的权值和
注意:从点u到点v的路径上的节点包括u和v本身
Solution
链剖裸题。。。。。。
Code
#include<cstdio>#include<cstdlib>#include<algorithm>#include<iostream>#include<cstring>#include<cmath>#define fo(i,a,b) for(i=a;i<=b;i++)#define fod(i,a,b) for(i=a;i>=b;i--)using namespace std;struct note{ int l,r,sum,mx,ls,rs; };struct nt1{ int x,y; };note tree[100001];int top[30001],deep[30001],size[30001],pt[30001],dfn[30001],ft[30001],son[30001],a[30001],lazy[100001];nt1 a1[60001];int a2[30001][2];int n,m,dfm;bool cmp(nt1 x,nt1 y){ return x.x<y.x;}void give(int f,int k){ tree[k].mx=lazy[f]; tree[k].sum=(tree[k].r-tree[k].l+1)*lazy[f];}void newptl(int f,int l,int r){ if (tree[f].ls==0) { tree[f].ls=++m; tree[m].l=l; tree[m].r=r; }}void newptr(int f,int l,int r){ if (tree[f].rs==0) { tree[f].rs=++m; tree[m].l=l; tree[m].r=r; }}void find(int now,int l,int r,int &sm,int &ma){ if (tree[now].l==l&&tree[now].r==r) { sm=tree[now].sum; ma=tree[now].mx; return; } int ls=tree[now].ls,rs=tree[now].rs; if (lazy[now]!=1802201963) { if (ls!=0) give(now,ls); if (rs!=0) give(now,rs); lazy[now]=1802201963; } int mid=(tree[now].l+tree[now].r)/2; if (r<=mid) find(ls,l,r,sm,ma); else if(l>mid) find(rs,l,r,sm,ma); else { int s1,m1; find(ls,l,mid,sm,ma); find(rs,mid+1,r,s1,m1); sm+=s1; ma=max(ma,m1); } tree[now].sum=tree[tree[now].ls].sum+tree[tree[now].rs].sum; tree[now].mx=max(tree[tree[now].ls].mx,tree[tree[now].rs].mx);}void ask(int u,int v,int &sm,int &ma,bool uh,bool vh){ int s1=0,m1=-1802201963,s2=0,m2=-1802201963; if (u==v) { if (uh==0&&vh==0) { find(1,dfn[u],dfn[v],s1,m1); sm=s1; ma=m1; return; } sm=0; ma=-1802201963; return; } int f1=top[u],f2=top[v]; if (f1==f2) { if (deep[u]>deep[v]) swap(u,v); find(1,dfn[u],dfn[v],sm,ma); return; } else { if (deep[f1]<deep[f2]) { swap(u,v); swap(f1,f2); swap(uh,vh); } find(1,dfn[f1],dfn[u],s1,m1); if (ft[f1]==f1) ask(ft[f1],v,s2,m2,1,vh); else ask(ft[f1],v,s2,m2,0,vh); sm=s1+s2; ma=max(m1,m2); }}void change(int now,int l,int r,int dt){ if (tree[now].l==l&&tree[now].r==r) { tree[now].mx=dt; tree[now].sum=(r-l+1)*dt; lazy[now]=dt; return; } int ls=tree[now].ls,rs=tree[now].rs; int mid=(tree[now].l+tree[now].r)/2; if (lazy[now]!=1802201963) { if (ls!=0) give(now,ls); if (rs!=0) give(now,rs); lazy[now]=1802201963; } if (r<=mid) { newptl(now,tree[now].l,mid); change(tree[now].ls,l,r,dt); } else if(l>mid) { newptr(now,mid+1,tree[now].r); change(tree[now].rs,l,r,dt); } else { newptl(now,tree[now].l,mid); newptr(now,mid+1,tree[now].r); change(tree[now].ls,l,mid,dt); change(tree[now].rs,mid+1,r,dt); } tree[now].sum=tree[tree[now].ls].sum+tree[tree[now].rs].sum; tree[now].mx=max(tree[tree[now].ls].mx,tree[tree[now].rs].mx);}void dfs1(int k,int f,int dep){ int i,sz=0,sn=0,wsn=0; fo(i,a2[k][0],a2[k][1]) { int p=a1[i].y; if (p!=f) { ft[p]=k; dfs1(p,k,dep+1); sz+=size[p]; if (size[p]>sn) { sn=size[p]; wsn=p; } } } size[k]=sz+1; son[k]=wsn; deep[k]=dep;}void dfs2(int k,int f){ dfn[k]=++dfm; change(1,dfn[k],dfn[k],a[k]); int i; if (son[k]!=0) { top[son[k]]=top[k]; dfs2(son[k],k); } fo(i,a2[k][0],a2[k][1]) { int p=a1[i].y; if (p!=f&&p!=son[k]) { top[p]=p; dfs2(p,k); } }}int main(){ cin>>n; int i,j,s1,m1; fo(i,1,n-1) { scanf("%d%d",&a1[2*i-1].x,&a1[2*i-1].y); a1[2*i].x=a1[2*i-1].y; a1[2*i].y=a1[2*i-1].x; } sort(a1+1,a1+2*n-1,cmp); fo(i,1,2*n-2) { if (a1[i].x!=a1[i-1].x) { a2[a1[i].x][0]=i; a2[a1[i-1].x][1]=i-1; } } a2[a1[2*n-2].x][1]=2*n-2; fo(i,1,n) scanf("%d",&a[i]); memset(lazy,107,sizeof(lazy)); dfs1(1,0,1); dfm=0; top[1]=1; m=1; tree[1].l=1; tree[1].r=n; dfs2(1,0); ft[1]=1; scanf("\n"); int cz; scanf("%d",&cz); scanf("\n"); int ct=0; fo(i,1,cz) { char c,c1; scanf("%c%c",&c,&c1); if (c=='C') { int x,t; scanf("ANGE %d%d\n",&x,&t); change(1,dfn[x],dfn[x],t); } else { int su,ma,u,v; if (c1=='M') scanf("AX %d%d\n",&u,&v); else scanf("UM %d%d\n",&u,&v); if (u==v) find(1,dfn[u],dfn[v],su,ma); else ask(u,v,su,ma,0,0); if (c1=='M') printf("%d\n",ma); else printf("%d\n",su); } }}
0 0
- [BZOJ1036][JZOJ2256]【ZJOI2008】树的统计(树链剖分模板)
- 树链剖分基础模板(BZOJ1036[ZJOI2008]树的统计Count)
- bzoj1036 [ZJOI2008]树的统计(树链剖分)
- 【树链剖分模板】【bzoj1036】: [ZJOI2008]树的统计Count
- bzoj1036 [ZJOI2008]树的统计Count 树链剖分模板题
- BZOJ1036 [ZJOI2008]树的统计Count 树链剖分
- bzoj1036 codevs2460: [ZJOI2008]树的统计 树链剖分
- 【BZOJ1036】[ZJOI2008]树的统计Count 树链剖分
- 【bzoj1036】【树链剖分】【ZJOI2008】树的统计Count
- 【BZOJ1036】【ZJOI2008】【树的统计count】【树链剖分】
- BZOJ1036: [ZJOI2008]树的统计Count (树链剖分)
- bzoj1036: [ZJOI2008]树的统计Count - 树链剖分
- 【树链剖分】[BZOJ1036][ZJOI2008]树的统计Count
- [树链剖分] BZOJ1036: [ZJOI2008]树的统计Count
- [bzoj1036][ZJOI2008]树的统计Count 树链剖分
- 【bzoj1036】【树链剖分】 [ZJOI2008]树的统计Count
- BZOJ1036 [ZJOI2008]树的统计Count(树链剖分)
- [BZOJ1036][ZJOI2008]树的统计Count(树链剖分)
- MySQL入门——查看指定表的索引情况的两种方式
- Shell脚本学习之sed详解
- 初探:celery在django下的应用.md
- hscode & equals
- 芯片新知识
- [BZOJ1036][JZOJ2256]【ZJOI2008】树的统计(树链剖分模板)
- 数据库--Orcal--day04
- Java基础部分
- FleaPHP的单入口文件详解
- Android源码解析(二十四)-->onSaveInstanceState执行时机
- 霍夫曼编码
- HDOJ 3415 Max Sum of Max-K-sub-sequence(线段树优化DP)
- mavlink的Java语言之探索实现
- POJ 1987Distance Statistics 树的分治