zoukankan      html  css  js  c++  java
  • BZOJ4127 : Abs

    树链剖分+线段树。

    线段树每个区间[l,r]维护:

    m:最大的负数

    s:所有数字绝对值的和

    d:正数的个数-负数的个数

    t:懒惰标记

    区间修改时,若最大的负数<0且最大的负数+p>=0,则暴力递归,否则打标记。

    因为每个负数只会被暴力修改一次,所以时间复杂度为$O(nlog^2n)$。

    #include<cstdio>
    #define N 100010
    typedef long long ll;
    int n,m,i,op,x,y,z,a[N];ll ans;
    int g[N],v[N<<1],nxt[N<<1],ed,size[N],son[N],f[N],d[N],top[N],loc[N],dfn,seq[N];
    struct P{
      ll m,s,t;int d;
      P(){}
      inline void set(int x){
        t=0;
        if(x<0)m=x,s=-x,d=-1;else m=0,s=x,d=1;
      }
    }T[262145];
    inline int merge(int a,int b){
      if(a>=0&&b>=0)return 0;
      if(a>=0)return b;
      if(b>=0)return a;
      return a>b?a:b;
    }
    inline void add1(int x,ll p){
      T[x].m+=p;
      T[x].s+=p*T[x].d;
      T[x].t+=p;
    }
    inline void pb(int x){if(T[x].t)add1(x<<1,T[x].t),add1(x<<1|1,T[x].t),T[x].t=0;}
    inline void up(int x){
      T[x].m=merge(T[x<<1].m,T[x<<1|1].m);
      T[x].s=T[x<<1].s+T[x<<1|1].s;
      T[x].d=T[x<<1].d+T[x<<1|1].d;
    }
    void build(int x,int a,int b){
      if(a==b){T[x].set(seq[a]);return;}
      int mid=(a+b)>>1;
      build(x<<1,a,mid),build(x<<1|1,mid+1,b),up(x);
    }
    void change(int x,int a,int b,int c,int d,int p){
      if(c<=a&&b<=d&&(T[x].m>=0||T[x].m+p<0)){add1(x,p);return;}
      if(a==b){T[x].set(T[x].m+p);return;}
      pb(x);
      int mid=(a+b)>>1;
      if(c<=mid)change(x<<1,a,mid,c,d,p);
      if(d>mid)change(x<<1|1,mid+1,b,c,d,p);
      up(x);
    }
    void ask(int x,int a,int b,int c,int d){
      if(c<=a&&b<=d){ans+=T[x].s;return;}
      pb(x);
      int mid=(a+b)>>1;
      if(c<=mid)ask(x<<1,a,mid,c,d);
      if(d>mid)ask(x<<1|1,mid+1,b,c,d);
      up(x);
    }
    inline void add(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
    void dfs(int x,int y){
      size[x]=1,d[x]=d[f[x]=y]+1;
      for(int i=g[x];i;i=nxt[i])if(v[i]!=y){
        dfs(v[i],x);size[x]+=size[v[i]];
        if(size[v[i]]>size[son[x]])son[x]=v[i];
      }
    }
    void dfs2(int x,int y){
      top[x]=y;seq[loc[x]=++dfn]=a[x];
      if(son[x])dfs2(son[x],y);
      for(int i=g[x];i;i=nxt[i])if(v[i]!=son[x]&&v[i]!=f[x])dfs2(v[i],v[i]);
    }
    inline void modify(int x,int y,int p){
      for(;top[x]!=top[y];x=f[top[x]]){
        if(d[top[x]]<d[top[y]]){int z=x;x=y;y=z;}
        change(1,1,n,loc[top[x]],loc[x],p);
      }
      if(d[x]<d[y]){int z=x;x=y;y=z;}
      change(1,1,n,loc[y],loc[x],p);
    }
    inline void query(int x,int y){
      for(ans=0;top[x]!=top[y];x=f[top[x]]){
        if(d[top[x]]<d[top[y]]){int z=x;x=y;y=z;}
        ask(1,1,n,loc[top[x]],loc[x]);
      }
      if(d[x]<d[y]){int z=x;x=y;y=z;}
      ask(1,1,n,loc[y],loc[x]);
      printf("%lld
    ",ans);
    }
    inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
    inline void read2(int&a){
      char c;bool f=0;a=0;
      while(!((((c=getchar())>='0')&&(c<='9'))||(c=='-')));
      if(c!='-')a=c-'0';else f=1;
      while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';
      if(f)a=-a;
    }
    int main(){
      read(n),read(m);
      for(i=1;i<=n;i++)read2(a[i]);
      for(i=1;i<n;i++)read(x),read(y),add(x,y),add(y,x);
      dfs(1,0),dfs2(1,1),build(1,1,n);
      while(m--){
        read(op),read(x),read(y);
        if(op==1)read(z),modify(x,y,z);else query(x,y);
      }
      return 0;
    }
    

      

  • 相关阅读:
    简历
    Servlet 三大域对象
    jsp分页
    fastadmin开发api的时候,遇到一些疑问
    RSA的基本原理,B站视频2部
    php函数注释规范
    vscode查看函数跳转定义处,和跳转引用处
    api接口发的规范和具体的细节
    restful规范是什么?为什么推荐使用restful风格,他的好处是什么?
    在线考试系统的逻辑思路
  • 原文地址:https://www.cnblogs.com/clrs97/p/4782646.html
Copyright © 2011-2022 走看看