bzoj 1036 //1036: [ZJOI2008]树的统计Count 树链剖分

bzoj 1036   //1036: [ZJOI2008]树的统计Count   树链剖分

bzoj 1036   //1036: [ZJOI2008]树的统计Count   //在线测评地址https://www.lydsy.com/JudgeOnline/problem.php?id=1036

更多题解,详见https://blog.csdn.net/mrcrack/article/details/90228694BZOJ刷题记录

1036Accepted5560 kb3208 msC++/Edit3362 B

//1036: [ZJOI2008]树的统计Count
//在线测评地址https://www.lydsy.com/JudgeOnline/problem.php?id=1036
//n=30000,w=30000,n*w=9*10^8 int不会溢出。
//采用树链剖分算法,若不清楚,详见https://blog.csdn.net/mrcrack/article/details/102884839
//树链剖分算法,遇到段错误,算是常事了。
//反复排查,linux在main函数内不好排查段错误,必须深入到具体函数内部去,增加了不少工作量。
/*
a[k].l=a[k].r=l,a[k].mx=a[k].sum=v[rk[l]];//此处错写成a[k].l=a[k].r,a[k].mx=a[k].sum=v[rk[l]];查了2个小时.2019-11-3 20:39
一处不起眼的错误啊。
*/
//样例通过,提交AC.2019-11-3 20:43   收获,对线段树节点的改、查,理解更深刻了。
#include <stdio.h>
#include <string.h>
#define lson k<<1
#define rson k<<1|1
#define maxn 30100
struct node1{
    int to,next;
}e[maxn<<1];
struct node2{
    int l,r,sum,mx;
}a[maxn<<2];
int v[maxn],n,head[maxn],R=1,d[maxn],fa[maxn],size[maxn],son[maxn],id[maxn],rk[maxn],cnt,top[maxn];
int max(int a,int b){
    return a>b?a:b;
}
void add_edge(int u,int v){
    cnt++,e[cnt].to=v,e[cnt].next=head[u],head[u]=cnt;
}
void dfs1(int x){
    int v,b;
    d[x]=d[fa[x]]+1,size[x]=1;
    for(b=head[x];b;b=e[b].next){
        v=e[b].to;
        if(v!=fa[x]){
            fa[v]=x,dfs1(v),size[x]+=size[v];
            if(size[son[x]]<size[v])son[x]=v;
        }
    }
}
void dfs2(int x,int tp){
    int v,b;
    top[x]=tp,cnt++,rk[cnt]=x,id[x]=cnt;
    if(son[x])dfs2(son[x],tp);
    for(b=head[x];b;b=e[b].next){
        v=e[b].to;
        if(v!=fa[x]&&v!=son[x])dfs2(v,v);
    }
}
void pushup(int k){
    a[k].sum=a[lson].sum+a[rson].sum;
    a[k].mx=max(a[lson].mx,a[rson].mx);
}
void update(int l,int r,int c,int k){
    int mid=(a[k].l+a[k].r)/2;
    if(l<=a[k].l&&a[k].r<=r){
        a[k].sum=a[k].mx=c;
        return;
    }
    if(l<=mid)update(l,r,c,lson);
    if(mid+1<=r)update(l,r,c,rson);
    pushup(k);
}
int qmax(int l,int r,int k){
    int mid=(a[k].l+a[k].r)/2,ret=-30100;//此处错写成int mid=(a[k].l+a[k].r)/2,ret=-1;
    if(l<=a[k].l&&a[k].r<=r){
        return a[k].mx;
    }
    if(l<=mid)ret=max(ret,qmax(l,r,lson));
    if(mid+1<=r)ret=max(ret,qmax(l,r,rson));
    return ret;
}
void swap(int *a,int *b){
    int t;
    t=*a,*a=*b,*b=t;
}
int qmaxs(int x,int y,int k){
    int ret=-30100;//此处错写成int ret=-1;
    while(top[x]!=top[y]){
        if(d[top[x]]<d[top[y]])swap(&x,&y);
        ret=max(ret,qmax(id[top[x]],id[x],1)),x=fa[top[x]];
    }
    if(id[x]>id[y])swap(&x,&y);
    ret=max(ret,qmax(id[x],id[y],1));//此处错写成ret=(ret,qmax(id[x],id[y],1));
    return ret;
}
int qsum(int l,int r,int k){
    int mid=(a[k].l+a[k].r)/2,ret=0;
    if(l<=a[k].l&&a[k].r<=r){
        return a[k].sum;
    }
    if(l<=mid)ret+=qsum(l,r,lson);
    if(mid+1<=r)ret+=qsum(l,r,rson);
    return ret;
}
int qsums(int x,int y,int k){
    int ret=0;
    while(top[x]!=top[y]){
        if(d[top[x]]<d[top[y]])swap(&x,&y);
        ret+=qsum(id[top[x]],id[x],1),x=fa[top[x]];
    }
    if(id[x]>id[y])swap(&x,&y);
    ret+=qsum(id[x],id[y],1);
    return ret;
}
void build(int l,int r,int k){
    int mid=(l+r)/2;
    if(l==r){
        a[k].l=a[k].r=l,a[k].mx=a[k].sum=v[rk[l]];//此处错写成a[k].l=a[k].r,a[k].mx=a[k].sum=v[rk[l]];查了2个小时.2019-11-3 20:39
        return;
    }
    build(l,mid,lson);
    build(mid+1,r,rson);
    a[k].l=l,a[k].r=r,pushup(k);
}
int main(){
    int i,a,b,q;
    char cmd[10];
    scanf("%d",&n),memset(head,0,sizeof(head)),cnt=0;
    for(i=1;i<n;i++)scanf("%d%d",&a,&b),add_edge(a,b),add_edge(b,a);
    for(i=1;i<=n;i++)scanf("%d",&v[i]);
    memset(son,0,sizeof(son)),fa[R]=0,d[0]=0,dfs1(R);
    cnt=0,dfs2(R,R);
    build(1,n,1);
    scanf("%d",&q);
    while(q--){
        scanf("%s",cmd);
        if(cmd[1]=='M')scanf("%d%d",&a,&b),printf("%d\n",qmaxs(a,b,1));
        else if(cmd[1]=='S')scanf("%d%d",&a,&b),printf("%d\n",qsums(a,b,1));
        else if(cmd[1]=='H')scanf("%d%d",&a,&b),update(id[a],id[a],b,1);
    }
    return 0;
}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
牙科就诊管理系统利用当下成熟完善的SSM框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的Mysql数据库进行程序开发。实现了用户在线查看数据。管理员管理病例管理、字典管理、公告管理、药单管理、药品管理、药品收藏管理、药品评价管理、药品订单管理、牙医管理、牙医收藏管理、牙医评价管理、牙医挂号管理、用户管理、管理员管理等功能。牙科就诊管理系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。 管理员在后台主要管理病例管理、字典管理、公告管理、药单管理、药品管理、药品收藏管理、药品评价管理、药品订单管理、牙医管理、牙医收藏管理、牙医评价管理、牙医挂号管理、用户管理、管理员管理等。 牙医列表页面,此页面提供给管理员的功能有:查看牙医、新增牙医、修改牙医、删除牙医等。公告信息管理页面提供的功能操作有:新增公告,修改公告,删除公告操作。公告类型管理页面显示所有公告类型,在此页面既可以让管理员添加新的公告信息类型,也能对已有的公告类型信息执行编辑更新,失效的公告类型信息也能让管理员快速删除。药品管理页面,此页面提供给管理员的功能有:新增药品,修改药品,删除药品。药品类型管理页面,此页面提供给管理员的功能有:新增药品类型,修改药品类型,删除药品类型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值