zoukankan      html  css  js  c++  java
  • 【BZOJ】1984 月下“毛景树”

    【算法】树链剖分+线段树

    【题解】线段树的区间加值和区间覆盖操作不能同时存在,只能存在一个。

    修改:从根节点跑到目标区域路上的标记全部下传,打完标记再上传回根节点(有变动才需要上传)。

    询问:访问到目标区域路上的标记全部下传。

    我写的线段树版本是在打标记的同时便对该点的询问项(最大值)做了对应更改,即可保证访问到该点得到的ms就是该点的答案。

    访问某点时如果要询问最大值就直接拿走,如果要还要访问该点的子节点就需要下传。

    而修改了某点的值,它的祖先的值就都需要变动,所以一旦修改必须上传至顶。

    对于add和cover不共存的问题,下传过程:

    void pushdown(int k)
    {
        if(t[k].l==t[k].r)return;
        if(t[k].c!=-1)
         {
             t[k<<1].a=t[k<<1|1].a=0;
             t[k<<1].c=t[k<<1|1].c=t[k].c;
             t[k<<1].ms=t[k<<1|1].ms=t[k].c;
             t[k].c=-1;
         }
        if(t[k].a!=0)
         {
             if(t[k<<1].c!=-1)t[k<<1].c+=t[k].a;
              else t[k<<1].a+=t[k].a;
             if(t[k<<1|1].c!=-1)t[k<<1|1].c+=t[k].a;
              else t[k<<1|1].a+=t[k].a;
             t[k<<1].ms+=t[k].a;t[k<<1|1].ms+=t[k].a;
             t[k].a=0;
         }
    }

    下传cover时,子树add'=0,cover'=cover,ms=cover

    下传add时,就要看子树的标记是cover还是add了。

    边权赋给下面的点,注意LCA不算(树剖过程中顺便处理即可,不必写倍增)

    不在同一条重链时,是deep[top[u]]大的先,不是deep[u]。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int maxn=200010,inf=0x3f3f3f3f;
    struct tree{int l,r,c,a,ms;}t[maxn*3];
    struct edge{int v,w,from;}e[maxn*3];
    int dfsnum,n,pos[maxn],size[maxn],first[maxn],deep[maxn],f[maxn],id[maxn*3],tot,top[maxn];
    void insert(int u,int v,int w)
    {tot++;e[tot].v=v;e[tot].w=w;e[tot].from=first[u];first[u]=tot;}
    void build(int k,int l,int r)
    {
        t[k].l=l;t[k].r=r;t[k].c=-1;
        if(l!=r)
         {
             int mid=(l+r)>>1;
             build(k<<1,l,mid);
             build(k<<1|1,mid+1,r);
         }
    }
    void pushdown(int k)
    {
        if(t[k].l==t[k].r)return;
        if(t[k].c!=-1)
         {
             t[k<<1].a=t[k<<1|1].a=0;
             t[k<<1].c=t[k<<1|1].c=t[k].c;
             t[k<<1].ms=t[k<<1|1].ms=t[k].c;
             t[k].c=-1;
         }
        if(t[k].a!=0)
         {
             if(t[k<<1].c!=-1)t[k<<1].c+=t[k].a;
              else t[k<<1].a+=t[k].a;
             if(t[k<<1|1].c!=-1)t[k<<1|1].c+=t[k].a;
              else t[k<<1|1].a+=t[k].a;
             t[k<<1].ms+=t[k].a;t[k<<1|1].ms+=t[k].a;
             t[k].a=0;
         }
    }
    void pushup(int k)
    {
        t[k].ms=max(t[k<<1].ms,t[k<<1|1].ms);
    }
    void cover(int k,int l,int r,int x)
    {
        int left=t[k].l,right=t[k].r;
        pushdown(k);
        if(l<=left&&right<=r)t[k].c=x,t[k].ms=x;
         else
          {
              int mid=(left+right)>>1;
              if(l<=mid)cover(k<<1,l,r,x);
              if(r>mid)cover(k<<1|1,l,r,x);
              pushup(k);
          }
    }
    void add(int k,int l,int r,int x)
    {
        int left=t[k].l,right=t[k].r;
        pushdown(k);
        if(l<=left&&right<=r)t[k].a+=x,t[k].ms+=x;
         else
          {
              int mid=(left+right)>>1;
              if(l<=mid)add(k<<1,l,r,x);
              if(r>mid)add(k<<1|1,l,r,x);
              pushup(k);
          }
    }
    int ask(int k,int l,int r)
    {
        int left=t[k].l,right=t[k].r;
        if(l<=left&&right<=r)return t[k].ms;
         else
          {
              int mid=(left+right)>>1;
              pushdown(k);int mss=-inf;
              if(l<=mid)mss=ask(k<<1,l,r);
              if(r>mid)mss=max(mss,ask(k<<1|1,l,r));
              return mss;
          }
    }
    void solve_cover()
    {
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        while(top[u]!=top[v])
         {
             if(deep[top[u]]<deep[top[v]])swap(u,v);
             cover(1,pos[top[u]],pos[u],w);
             u=f[top[u]];
         }
        if(pos[u]>pos[v])swap(u,v);
        if(pos[u]<pos[v])cover(1,pos[u]+1,pos[v],w);
    }
    void solve_add()
    {
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        while(top[u]!=top[v])
         {
           if(deep[top[u]]<deep[top[v]])swap(u,v);
             add(1,pos[top[u]],pos[u],w);
             u=f[top[u]];
         }
        if(pos[u]>pos[v])swap(u,v);
        if(pos[u]<pos[v])add(1,pos[u]+1,pos[v],w);
    }
    void ask_max()
    {
        int u,v;
        scanf("%d%d",&u,&v);
        int maxs=-inf;
        while(top[u]!=top[v])
         {
             if(deep[top[u]]<deep[top[v]])swap(u,v);
             maxs=max(maxs,ask(1,pos[top[u]],pos[u]));
             u=f[top[u]];
         }
        if(pos[u]>pos[v])swap(u,v);
        if(pos[u]<pos[v])maxs=max(maxs,ask(1,pos[u]+1,pos[v]));
        printf("%d
    ",maxs);
    }
    void dfs1(int x,int fa)
    {
        size[x]=1;
        for(int i=first[x];i;i=e[i].from)
         if(e[i].v!=fa)
          {
              int y=e[i].v;
              deep[y]=deep[x]+1;
              f[y]=x;
              dfs1(y,x);
              size[x]+=size[y];
          }
    }
    void dfs2(int x,int tp,int fa)
    {
        pos[x]=++dfsnum;
        top[x]=tp;
        int k=0;
        for(int i=first[x];i;i=e[i].from)
         if(e[i].v!=fa){if(size[e[i].v]>size[k])k=e[i].v;}
          else id[(i+1)>>1]=x,add(1,pos[x],pos[x],e[i].w);
        if(k==0)return;//!!!
        dfs2(k,tp,x);
        for(int i=first[x];i;i=e[i].from)
         if(e[i].v!=fa&&e[i].v!=k)dfs2(e[i].v,e[i].v,x);
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<n;i++)
         {
             int u,v,w;
             scanf("%d%d%d",&u,&v,&w);
             insert(u,v,w);
             insert(v,u,w);
         }
        build(1,1,n);
        dfs1(1,-1);
        dfs2(1,1,-1);
        char st[10];int u,v;
        for(;;)
         {
             scanf("%s",st);
             if(st[1]=='h')//change
              {
                  scanf("%d%d",&u,&v);
                  cover(1,pos[id[u]],pos[id[u]],v);
              }
             if(st[1]=='o')solve_cover();//cover
             if(st[1]=='d')solve_add();//add
             if(st[1]=='a')ask_max();//max
             if(st[1]=='t')break;//stop
         }
        return 0;
    }
    View Code
  • 相关阅读:
    Did not find handler method for springMVC资源文件扫描不到---关于spring的那些坑
    mysql中OPTIMIZE TABLE的作用
    Linux环境下apache性能测试工具ab使用详解
    sqlite数据库 adb 从配置到查询表中数据全过程-----献给初学的自己
    c3p0参数解释
    linux下如何启动/停止/重启mysql:
    [MySQL] 变量(参数)的查看和设置
    mysql运行参数详解
    单例模式 理解,简单通透
    this的一些场景
  • 原文地址:https://www.cnblogs.com/onioncyc/p/6399077.html
Copyright © 2011-2022 走看看