http://www.lydsy.com/JudgeOnline/problem.php?id=1036 (题目链接)

题意

  动态维护树上两点间最大权值和权值和。

Solution

  裸树链剖分。

  这一篇题解并不是本博客的重点。我在找本题的数据生成器的时候发现了一篇神奇的博客。关于如何制造出一棵树的数据,随机构造prufer。

  UPD:当年的自己真是脑残,竟然不会构造树的数据→_→

data

#include<cstdio>
#include<iostream>
#include<ctime>
#include<cstdlib>
#include<algorithm>
using namespace std;
int a[30000+20];
struct nod
{int id,d;
}d[30000+20];
bool cmpid(nod x,nod y)//按编号排序
{return x.id<y.id;
}
bool cmp(nod x,nod y)//按度数排序
{if(x.d!=y.d)return x.d<y.d;else return x.id<y.id;
}
int main()
{freopen("1.in","w",stdout);srand(time(NULL));int n=rand()%10+1;cout<<n<<endl;for(int i=1;i<=n;i++){d[i].d=1;d[i].id=i;}for(int i=1;i<=n-2;i++)a[i]=rand()%n+1;//生成purfer编码for(int i=1;i<=n-2;i++)d[a[i]].d++;//累加度数for(int i=1;i<=n-2;i++){sort(d+1,d+n+1,cmp);int j;for(j=1;j<=n;j++)if(d[j].d)break;printf("%d %d\n",d[j].id,a[i]);d[j].d--;sort(d+1,d+n+1,cmpid);d[a[i]].d--;}                                //模拟上述过程,找度数为1且编号最小的和purfer编码中当前位sort(d+1,d+n+1,cmp);printf("%d %d\n",d[n-1].id,d[n].id);//最后两个点之间连边for(int i=1;i<=n;i++){printf("%d ",(rand()%20)-10);}int m=rand()%20+1;cout<<endl;cout<<m<<endl;for(int i=1;i<=m;i++){int s=rand()%3+1;if(s==1)printf("QMAX ");if(s==2)printf("QSUM ");if(s==3)printf("CHANGE ");int a=rand()%n+1;int b=rand()%a+1;while(a==b){a=rand()%n+1;b=rand()%a+1;}cout<<a<<" "<<b<<endl;}return 0;
}

代码

// bzoj1036
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<map>
#define inf 2147483640
#define LL long long
#define free(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout);
using namespace std;
inline LL getint() {LL x=0,f=1;char ch=getchar();while (ch>'9' || ch<'0') {if (ch=='-') f=-1;ch=getchar();}while (ch>='0' && ch<='9') {x=x*10+ch-'0';ch=getchar();}return x*f;
}const int maxn=30010;
struct edge {int to,next;}e[maxn<<2];
struct tree {int s,mx,l,r;}tr[maxn<<2];
int a[maxn],pos[maxn],head[maxn],bl[maxn],size[maxn],deep[maxn],fa[maxn][20],bin[20];
int cnt,n,q;void insert(int u,int v) {e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;e[++cnt].to=u;e[cnt].next=head[v];head[v]=cnt;
}
void build(int k,int s,int t) {tr[k].l=s,tr[k].r=t,tr[k].s=0,tr[k].mx=-inf;if (s==t) return;int mid=(s+t)>>1;build(k<<1,s,mid);build(k<<1|1,mid+1,t);
}
void update(int k,int s,int val) {int l=tr[k].l,r=tr[k].r;if (l==r && l==s) {tr[k].s=tr[k].mx=val;return;}int mid=(l+r)>>1;if (s<=mid) update(k<<1,s,val);else update(k<<1|1,s,val);tr[k].s=tr[k<<1].s+tr[k<<1|1].s;tr[k].mx=max(tr[k<<1].mx,tr[k<<1|1].mx);
}
int querymx(int k,int s,int t) {int l=tr[k].l,r=tr[k].r;if (l==s && r==t) return tr[k].mx;int mid=(l+r)>>1;if (t<=mid) return querymx(k<<1,s,t);else if (s>mid) return querymx(k<<1|1,s,t);else return max(querymx(k<<1,s,mid),querymx(k<<1|1,mid+1,t));
}
int querys(int k,int s,int t) {int l=tr[k].l,r=tr[k].r;if (l==s && r==t) return tr[k].s;int mid=(l+r)>>1;if (t<=mid) return querys(k<<1,s,t);else if (s>mid) return querys(k<<1|1,s,t);else return querys(k<<1,s,mid)+querys(k<<1|1,mid+1,t);
}
void dfs1(int x) {size[x]=1;for (int i=1;i<20;i++) fa[x][i]=fa[fa[x][i-1]][i-1];for (int i=head[x];i;i=e[i].next) if (e[i].to!=fa[x][0]) {deep[e[i].to]=deep[x]+1;fa[e[i].to][0]=x;dfs1(e[i].to);size[x]+=size[e[i].to];}
}
void dfs2(int x,int chain) {bl[x]=chain;pos[x]=++cnt;update(1,pos[x],a[x]);int k=0;for (int i=head[x];i;i=e[i].next) if (e[i].to!=fa[x][0])if (size[k]<size[e[i].to]) k=e[i].to;if (k!=0) dfs2(k,chain);for (int i=head[x];i;i=e[i].next)if (e[i].to!=fa[x][0] && e[i].to!=k) dfs2(e[i].to,e[i].to);
}
int lca(int x,int y) {if (deep[x]<deep[y]) swap(x,y);int t=deep[x]-deep[y];for (int i=0;bin[i]<=t;i++) if (bin[i]&t) x=fa[x][i];for (int i=19;i>=0;i--) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];return x==y?x:fa[x][0];
}
int solvemx(int x,int f) {if (x==f) return a[x];int mx=-inf;while (bl[x]!=bl[f]) {mx=max(mx,querymx(1,pos[bl[x]],pos[x]));x=fa[bl[x]][0];}if (pos[f]<=pos[x]) mx=max(mx,querymx(1,pos[f],pos[x]));return mx;
}
int solves(int x,int f) {if (x==f) return a[x];int s=0;while (bl[x]!=bl[f]) {s+=querys(1,pos[bl[x]],pos[x]);x=fa[bl[x]][0];}if (pos[f]<=pos[x]) s+=querys(1,pos[f],pos[x]);return s;
}
int main() {bin[0]=1;for (int i=1;i<20;i++) bin[i]=bin[i-1]<<1;scanf("%d",&n);for (int i=1;i<n;i++) {int u,v;scanf("%d%d",&u,&v);insert(u,v);}for (int i=1;i<=n;i++) scanf("%d",&a[i]);cnt=0;build(1,1,n);dfs1(1);dfs2(1,1);scanf("%d",&q);while (q--) {char ch[10];int x,y;scanf("%s%d%d",ch,&x,&y);if (ch[0]=='C') update(1,pos[x],y),a[x]=y;else if (ch[1]=='M') {int f=lca(x,y);printf("%d\n",max(solvemx(x,f),solvemx(y,f)));}else {int f=lca(x,y);printf("%d\n",solves(x,f)+solves(y,f)-a[f]);}}return 0;
}

  

转载于:https://www.cnblogs.com/MashiroSky/p/5914532.html

【bzoj1036】 ZJOI2008—树的统计Count相关推荐

  1. [bzoj1036][ZJOI2008]树的统计Count

    Description 一棵树上有$n$个节点,编号分别为$1$到$n$,每个节点都有一个权值$w_i$. 有三种操作: $1.CHANGE\;u\;t$:把结点$u$的权值改为$t$; $2.QMA ...

  2. bzoj1036: [ZJOI2008]树的统计Count 树链剖分

    一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从 ...

  3. BZOJ1036: [ZJOI2008]树的统计Count

    Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. Q ...

  4. [BZOJ1036][ZJOI2008]树的统计Count(树链剖分)

    树剖模板题了, Code #include <cstdio> #include <algorithm> #define MID int mid=(l+r)>>1,l ...

  5. BZOJ 1036: [ZJOI2008]树的统计Count

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 3427  Solved: 1429 [Submi ...

  6. 树链剖分(bzoj 1036: [ZJOI2008]树的统计Count)

    树链剖分: 把一棵树剖分为若干条链,然后利用数据结构(树状数组,SBT,Splay,线段树等等)去维护每一条链,复杂度 为O(logn),总体复杂度O(nlog²n) 步骤: ①将树的边分成重边和轻边 ...

  7. BZOJ 1036 [ZJOI2008]树的统计Count

    以前动态树写过这个题,今天尝试树链剖分解决~ 模板题,就声明一点,线段树维护的是点权 View Code 1 #include <iostream> 2 #include <cstd ...

  8. 【BZOJ 1036】[ZJOI2008]树的统计Count

    [题目链接]:http://www.lydsy.com/JudgeOnline/problem.php?id=1036 [题意] [题解] 树链剖分入门题; 每一条链维护一个线段树就好; uppest ...

  9. 树链剖分 - BZOJ 1036: [ZJOI2008]树的统计Count

    这是树链剖分的入门题,也是我学树链剖分的第一题. 树链剖分:就是把树中和线段树联系起来,求(u,v)路径中权值的最大值和其路径的权值和. 入门blog:http://blog.sina.com.cn/ ...

最新文章

  1. 进程状态控制-进程的撤销
  2. 初探设计:Java继承何时用?怎么用?
  3. Python :集合推导式和字典推导式
  4. java中输入char类型_java中如何输入char类型
  5. lua--面向对象使用middleclass
  6. 百度关键词抓取工具_VBA利用XMLHTTP抓取百度查询关键词结果的个数
  7. 01_SpringCoud 整合SpringCoud alibaba Nacos
  8. java preference,Java使用Preference类保存上一次记录的方法
  9. 【ANDROID游戏开发之六】在SURFACEVIEW中添加系统控件,并且相互交互数据!
  10. UCloud可支撑单可用区320,000服务器的数据中心网络系统设计
  11. java游戏开发入门(一) - HelloWorld
  12. Eucalyptus的结构
  13. Win10 安装MySQL(解压版)
  14. 工作流——流程设计器
  15. 牛逼哄哄的对象深复制
  16. mysql统计分数段人数_mysql 按分数段,每个专业分数段统计人数
  17. DotEPUB:一键将网页转换成 EPUB 格式电纸书
  18. 功率放大器P1dB、P3dB和PSat指标释义
  19. electron,win10,消息通知
  20. 电信及互联网行业数据安全内控审计建设实践 | 盾见

热门文章

  1. linux sz rz 下载与上传命令
  2. 经纪xx系统节点VIP案例介绍和深入分析异常
  3. DNS原理及其解析过程 精彩剖析
  4. apache伪静态综述
  5. MongoDB工具最新进展
  6. 双亲委派机制_史上三次破坏ClassLoader双亲委派机制
  7. matlab将图片旋转的代码_【MATLAB】钟表
  8. python实现isodd函数、参数为整数、如果整数为奇数_python 程序练习题
  9. 教育启蒙赛道、亿级异构数据不停服平滑迁移方案和实践
  10. 在B站更新BV标识后,如何查看视频原AV号?