hdu6039 Gear Up-线段树

来源:互联网 发布:伦纳德官方体测数据 编辑:程序博客网 时间:2024/06/15 11:59

题意:
给出n个齿轮的半径和n个齿轮之间的关系(角速度相等或线速度相等),两种操作,第一种操作:修改一个齿轮的半径,第二种操作:给一个齿轮角速度,输出最大的角速度,答案取ln(自然对数)。
Solution:
我们随意画一个图感受一下:
这里写图片描述
(粗边表示角速度相等,细边表示线速度相等,图中维护的是每个点的角速度和w1的关系)
我们可以发现一个规律:如果修改的点的父亲边是线边,那么到他线边所连的儿子的值是不包含这个点的半径的,也就是说,修改这个点的半径不会影响这个点线边所连的儿子,只会影响角边所连的儿子及儿子所在的子树;如果修改的点的父亲边是角边,那么只会影响这个点线边所连的儿子及儿子所在的子树,不影响这个点角边所连的儿子。

归纳一下:
修改一个点的半径r->r’,如果修改的点的父亲边是线边,那么角边所连的儿子及儿子所在的子树×rr,如果修改的点的父亲边是角边,那么线边所连的儿子及儿子所在的子树×rr
那么这道题就可以用线段树搞了,求出这棵树的dfs序,维护区间乘,区间取max即可,因为这道题要求取自然对数,所以我们可以维护ln值,就可以把区间乘转化为区间加了。

代码:

#include<cstdio>#include<iostream>#include<cstring>#include<cmath>using namespace std;const int N=100010;int n,m;int size,head[N];struct edg{    int from,to,next;    double v;}g[2*N],e[2*N];int f[N];int q;int h[N],l[N],r[N],ll[N],rr[N];double ra[N];int fa[N];int T,x,y,a,rt[N],cnt;double v[N];bool p[N];struct tree{    int l,r;    double tag,maxn;}tr[4*N];void update(int i){    tr[i].maxn=max(tr[i<<1].maxn,tr[i<<1|1].maxn);    return;}void build(int i,int l,int r){    tr[i].l=l;tr[i].r=r;    tr[i].maxn=0;tr[i].tag=0;    if (l==r) {tr[i].maxn=v[l];return;}    int mid=(l+r)>>1;    build(i<<1,l,mid);    build(i<<1|1,mid+1,r);    update(i);}void addtag(int i,double x){    tr[i].tag+=x;    tr[i].maxn+=x;}void pushdown(int i){    if (tr[i].tag)    {        if (tr[i].l==tr[i].r) return;        addtag(i<<1,tr[i].tag);        addtag(i<<1|1,tr[i].tag);        tr[i].tag=0;    }}void modify(int i,int l,int r,double x){    int L=tr[i].l,R=tr[i].r;    if (l>R||r<L) return;    if (l<=L&&R<=r) {addtag(i,x);return;}    pushdown(i);    modify(i<<1,l,r,x);    modify(i<<1|1,l,r,x);    update(i);}double query(int i,int l,int r){    int L=tr[i].l,R=tr[i].r;    if (l>R||r<L) return -1e9;    if (l<=L&&R<=r) return tr[i].maxn;    pushdown(i);    double ans=-1e9;    ans=max(ans,query(i<<1,l,r));    ans=max(ans,query(i<<1|1,l,r));    return ans;}int find(int x){    if (fa[x]!=x) fa[x]=find(fa[x]);    return fa[x];}void add(int x,int y){    size++;    e[size].to=y;    e[size].next=head[x];    head[x]=size;}void ad(int x,int y,int f,double v){    size++;    g[size].to=y;    g[size].v=v;    g[size].from=f;    g[size].next=h[x];    h[x]=size;}void dfs(int root,int fa,int x,double dis){    rt[x]=root;    l[x]=++cnt;    v[cnt]=dis;    for (int i=h[x];i;i=g[i].next)    {        int y=g[i].to;        int xx=g[i].from;        if (y!=fa)        {            ll[xx]=min(ll[xx],cnt+1);            dfs(root,x,y,1.0*dis+g[i].v);            rr[xx]=max(rr[xx],cnt);        }        else p[xx]=1;    }    r[x]=cnt;}int main(){    while (scanf("%d%d%d",&n,&m,&q)!=EOF)    {        memset(p,0,sizeof(p));        memset(h,0,sizeof(h));        memset(head,0,sizeof(head));        memset(rt,0,sizeof(rt));         for (int i=1;i<=n;i++)            scanf("%lf",&ra[i]),ra[i]=log(ra[i]),fa[i]=i;        size=0;        for (int i=1;i<=m;i++)        {            scanf("%d%d%d",&a,&x,&y);            if (a==1) add(x,y),add(y,x);            else x=find(x),y=find(y),fa[x]=y;        }        size=0;        for (int i=1;i<=n;i++)        {            ll[i]=1e9,rr[i]=0;            for (int j=head[i];j;j=e[j].next)            {                int x=e[j].to;                ad(find(i),find(x),i,ra[i]-ra[x]);            }        }        cnt=0;        for (int i=1;i<=n;i++)if (find(i)==i&&!rt[i]) dfs(i,0,i,0.0);        build(1,1,cnt);        printf("Case #%d:\n",++T);        for (int i=1;i<=q;i++)        {            scanf("%d%d%d",&a,&x,&y);            double yy=log(y);            if (a==1)            {                if (p[x]) modify(1,l[find(x)],r[find(x)],-yy+ra[x]);                if (ll[x]<=rr[x]) modify(1,ll[x],rr[x],yy-ra[x]);                ra[x]=yy;            }            else            {                printf("%.3f\n",yy-query(1,l[find(x)],l[find(x)])+query(1,l[rt[find(x)]],r[rt[find(x)]]));            }        }    }}
阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 煤气 天然气 价格 改煤气管道多少钱 管道煤气和天然气 煤气泄漏报警器 煤气自动分析仪 人工煤气和天然气区别 煤气和电两用热水器 家用煤气泄漏报警器 煤气热水器中途熄火 罐装煤气是液化气吗 煤气烧烤炉怎么样 燃气灶能用煤气吗 小型煤气发生炉 电热水器和煤气热水器哪个好 家用煤气报警器 煤气是一氧化碳吗 天然气和煤气哪个划算 煤气热水器怎么安装 煤气阀门怎么装 煤气泄露报警器 一罐煤气多少立方 煤气热水器打不着火的原因 管道煤气热水器哪个牌子好 焦炉煤气燃烧机 煤气热水器的安装 煤气泄露检测仪 煤气蒸汽发生器 高炉煤气主要成分 煤气跟天然气的区别 家里煤气泄露怎么办 离心式煤气鼓风机 煤气检测报警仪 室内煤气管道安装规范 红外煤气分析仪 家用一罐煤气多少立方 煤气发生炉用什么煤 煤气发电机价格 煤气发生炉 淘汰 转炉煤气的成分 煤气发生炉站长 煤气热水器报警