zoukankan      html  css  js  c++  java
  • 洛谷P3038 牧草种植Grass Planting

    思路:

    首先,这道题的翻译是有问题的(起码现在是),查询的时候应该是查询某一条路径的权值,而不是某条边(坑死我了)。

    与平常树链剖分题目不同的是,这道题目维护的是边权,而不是点权,那怎么办呢?好像有点棘手诶,这是一种非常经典的题型,我们可以发现,一个点最多只有一个父亲!!!那,我们显然就可以用这个点的点权去代替它与它父亲之间的边权!!!然后这道题不就成了树链剖分水题了嘛?刚开始边权都是(0),那我们就根据题目给的边建边权为(0)的边。

    (nonono),还有一个坑点就是在路径查询和修改的时候,两点的(LCA)的点权是不能算在其中的,因为它的点权是(LCA)(LCA)父亲之间边的边权,注意这几个问题,那这题就真的是水题了!

    自己整理的题解

    具体实现看代码:

    #include<cstdio>
    #include<algorithm>
    #include<cctype>
    #define maxn 100007
    #define ls rt<<1
    #define rs rt<<1|1
    using namespace std;
    int n,m,head[maxn],d[maxn],son[maxn],siz[maxn],id[maxn],w[maxn];
    int num,cnt,sum[maxn<<2],lazy[maxn<<2],top[maxn],fa[maxn],a[maxn];
    char s[3];
    inline int qread() {
      char c=getchar();int num=0,f=1;
      for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
      for(;isdigit(c);c=getchar()) num=num*10+c-'0';
      return num*f;
    }
    struct node {
      int v,w,nxt;
    }e[maxn<<1];
    inline void ct(int u, int v, int w) {
      e[++num].v=v;
      e[num].w=w;
      e[num].nxt=head[u];
      head[u]=num;
    }
    inline void pushup(int rt) {
      sum[rt]=sum[ls]+sum[rs];
    }
    void build(int rt, int l, int r) {
      if(l==r) {
        sum[rt]=a[l];
        return;
      }
      int mid=(l+r)>>1;
      build(ls,l,mid);
      build(rs,mid+1,r);
      pushup(rt);
    }
    inline void pushdown(int rt, int len) {
      if(lazy[rt]) {
        sum[ls]+=(len-(len>>1))*lazy[rt];
        sum[rs]+=(len>>1)*lazy[rt];
        lazy[ls]+=lazy[rt],lazy[rs]+=lazy[rt];
        lazy[rt]=0;
      }
    }
    void modify(int rt, int l, int r, int L, int R, int val) {
      if(L>r||R<l) return;
      if(L<=l&&r<=R) {
        sum[rt]+=(r-l+1)*val;
        lazy[rt]+=val;
        return;
      }
      pushdown(rt,r-l+1);
      int mid=(l+r)>>1;
      modify(ls,l,mid,L,R,val),modify(rs,mid+1,r,L,R,val);
      pushup(rt);
    }
    int csum(int rt, int l, int r, int L, int R) {
      if(L>r||R<l) return 0;
      if(L<=l&&r<=R) return sum[rt];
      pushdown(rt,r-l+1);
      int mid=(l+r)>>1;
      return csum(ls,l,mid,L,R)+csum(rs,mid+1,r,L,R);
    }
    void dfs1(int u) {
      siz[u]=1;
      for(int i=head[u];i;i=e[i].nxt) {
        int v=e[i].v;
        if(v!=fa[u]) {
          d[v]=d[u]+1;
          fa[v]=u;
          w[u]=e[i].w;
          dfs1(v);
          siz[u]+=siz[v];
          if(siz[v]>siz[son[u]]) son[u]=v;
        }
      }
    }
    void dfs2(int u, int t) {
      id[u]=++cnt;
      top[u]=t;
      a[cnt]=w[u];
      if(son[u]) dfs2(son[u],t);
      for(int i=head[u];i;i=e[i].nxt) {
        int v=e[i].v;
        if(v!=fa[u]&&v!=son[u]) dfs2(v,v);
      }
    }
    void cal(int x, int y) {
      int fx=top[x],fy=top[y];
      while(fx!=fy) {
        if(d[fx]<d[fy]) swap(x,y),swap(fx,fy);
        modify(1,1,cnt,id[fx],id[x],1);
        x=fa[fx],fx=top[x];
      }
      if(id[x]>id[y]) swap(x,y);
      modify(1,1,cnt,id[x]+1,id[y],1);
    }
    int query(int x, int y) {
      int fx=top[x],fy=top[y],ans=0;
      while(fx!=fy) {
        if(d[fx]<d[fy]) swap(x,y),swap(fx,fy);
        ans+=csum(1,1,cnt,id[fx],id[x]);
        x=fa[fx],fx=top[x];
      }
      if(id[x]>id[y]) swap(x,y);
      ans+=csum(1,1,cnt,id[x]+1,id[y]);
      return ans;
    }
    int main() {
      n=qread(),m=qread();
      for(int i=1,u,v;i<n;++i) {
        u=qread(),v=qread();
        ct(u,v,0);ct(v,u,0);
      }
      dfs1(1);dfs2(1,1);build(1,1,n);
      for(int i=1,u,v;i<=m;++i) {
        scanf("%s",s);
        u=qread(),v=qread();
        if(s[0]=='P') cal(u,v);
        else printf("%d
    ",query(u,v));
      }
      return 0;
    }
    
  • 相关阅读:
    C#如何为程序打包发布应用(图解教程) (转)
    异步委托与多线程
    如何判断自己的WP7 SDK版本
    (转)c#实现WinRAR解压缩
    网页HTML代码大全
    byte[] ,image, bitmap之间的转换
    MS开发者应懂得知识
    StringFarmat控制字符串居中显示
    WP7模拟器的感应器和GPS模拟定位功能
    lucene.net搜索文档(pdf,doc,txt)内容
  • 原文地址:https://www.cnblogs.com/grcyh/p/10201659.html
Copyright © 2011-2022 走看看