[bzoj4127] Abs

  链剖。线段树要记录区间内负数的个数,负数的最大值..

  如果增加后能使负数变正的话就往下暴力更新。。。

  时间复杂度O(nlog^2n)

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<cstdlib>
  5 #include<cmath>
  6 #define ll long long
  7 using namespace std;
  8 const int maxn=100233;
  9 struct zs{
 10     int too,pre;
 11 }e[maxn<<1];int tot1,last[maxn];
 12 int lc[maxn<<1],rc[maxn<<1],sz[maxn<<1],mx[maxn<<1],num[maxn<<1],tot;
 13 ll sm[maxn<<1],add[maxn<<1],V,SM;
 14 int dfn[maxn],tim,st[maxn],top,pos[maxn],bel[maxn],v[maxn],sz1[maxn],dep[maxn],fa[maxn],len[maxn],rt[maxn];
 15 int i,j,k,n,m,L,R;
 16  
 17 int ra,fh;char rx;
 18 inline int read(){
 19     rx=getchar(),ra=0,fh=1;
 20     while((rx<'0'||rx>'9')&&rx!='-')rx=getchar();
 21     if(rx=='-')fh=-1,rx=getchar();
 22     while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra*fh;
 23 }
 24  
 25  
 26 inline void upd(int x){
 27     int l=lc[x],r=rc[x];
 28     if(mx[l]==-1e9)mx[x]=mx[r]+add[r];else
 29     if(mx[r]==-1e9)mx[x]=mx[l]+add[l];else mx[x]=max(mx[l]+add[l],mx[r]+add[r]);
 30     if(mx[x]>=0)mx[x]=-1e9;
 31     sm[x]=sm[l]+sm[r],num[x]=num[l]+num[r];
 32 }
 33 inline void pushdown(int x){
 34     int l=lc[x],r=rc[x];
 35     if(mx[l]==-1e9)sm[l]+=add[x]*sz[l];
 36     else sm[l]+=add[x]*(sz[l]-num[l]-num[l]);
 37     if(mx[r]==-1e9)sm[r]+=add[x]*sz[r];
 38     else sm[r]+=add[x]*(sz[r]-num[r]-num[r]);
 39     add[l]+=add[x],add[r]+=add[x],
 40     add[x]=0;
 41 }
 42 void build(int a,int b){
 43     int x=++tot;sz[x]=b-a+1;
 44     if(a==b){
 45         sm[x]=abs(v[st[a]]);
 46         if(v[st[a]]<0)mx[x]=v[st[a]],num[x]=1;else mx[x]=-1e9;
 47         return;
 48     }
 49     int mid=a+b>>1;
 50     lc[x]=tot+1,build(a,mid),rc[x]=tot+1,build(mid+1,b);
 51     upd(x);
 52 //  printf("  %d--%d sm:%lld mx:%d\n",a,b,sm[x],mx[x]);
 53 }
 54 void insert(int x,int a,int b){
 55     if(L<=a&&R>=b){
 56         if(mx[x]==-1e9){sm[x]+=V*sz[x],add[x]+=V;return;}
 57         if(mx[x]+add[x]+V<0){sm[x]+=V*(sz[x]-num[x]-num[x]),add[x]+=V;return;}
 58     }
 59      
 60     if(a==b){
 61 //      printf("! %d %d\n",a,mx[x]);
 62         if(mx[x]+add[x]+V>=0)sm[x]=mx[x]+add[x]+V,mx[x]=-1e9,add[x]=num[x]=0;
 63         else add[x]+=V,sm[x]-=V;
 64 //      printf("  %d %lld\n",mx[x],sm[x]);
 65         return;
 66     }
 67     if(add[x])pushdown(x);
 68     int mid=a+b>>1;
 69     if(L<=mid)insert(lc[x],a,mid);
 70     if(R>mid)insert(rc[x],mid+1,b);
 71     upd(x);
 72 //  printf("ins:  %d--%d  sm:%lld mx:%d  num:%d\n",a,b,sm[x],mx[x],num[x]);
 73 }
 74 void query(int x,int a,int b){
 75     if(L<=a&&R>=b){SM+=sm[x];/*printf("%d--%d    %lld\n",a,b,sm[x]);*/return;}
 76     if(add[x])pushdown(x);
 77     int mid=a+b>>1;
 78     if(L<=mid)query(lc[x],a,mid);
 79     if(R>mid)query(rc[x],mid+1,b);
 80     upd(x);
 81 }
 82  
 83 void dfs(int x){
 84     sz1[x]=1,dep[x]=dep[fa[x]]+1;
 85     for(int i=last[x];i;i=e[i].pre)if(e[i].too!=fa[x])
 86         fa[e[i].too]=x,dfs(e[i].too),sz1[x]+=sz1[e[i].too];
 87 }
 88 void dfs2(int x,int chain){
 89     int mx=0,i;
 90     dfn[x]=++tim,pos[x]=tim-dfn[chain]+1,
 91     bel[x]=chain,st[++top]=x;
 92     for(i=last[x];i;i=e[i].pre)if(e[i].too!=fa[x]&&sz1[e[i].too]>sz1[mx])mx=e[i].too;
 93     if(!mx){
 94         len[chain]=pos[x],rt[chain]=tot+1,build(1,top),top=0;
 95         return;
 96     }else dfs2(mx,chain);
 97     for(i=last[x];i;i=e[i].pre)if(e[i].too!=fa[x]&&e[i].too!=mx)dfs2(e[i].too,e[i].too);
 98 }
 99 inline int getlca(int a,int b){
100     if(dep[bel[a]]<dep[bel[b]])swap(a,b);
101     while(bel[a]!=bel[b]){
102         a=fa[bel[a]];
103         if(dep[bel[a]]<dep[bel[b]])swap(a,b);
104     }
105     return dep[a]<dep[b]?a:b;
106 }
107  
108 void change(int a,int lca){
109     while(bel[a]!=bel[lca]){
110         L=1,R=pos[a],insert(rt[bel[a]],1,len[bel[a]]);
111         a=fa[bel[a]];
112     }
113     if(a!=lca)L=pos[lca]+1,R=pos[a],insert(rt[bel[a]],1,len[bel[a]]);
114 }
115 void query1(int a,int lca){//printf("Q %d %d\n",a,lca);
116     while(bel[a]!=bel[lca]){
117         L=1,R=pos[a],query(rt[bel[a]],1,len[bel[a]]);
118         a=fa[bel[a]];
119     }
120     if(a!=lca)L=pos[lca]+1,R=pos[a],/*printf("L R:  %d %d\n",L,R),*/query(rt[bel[a]],1,len[bel[a]]);
121 }
122 inline void insert(int a,int b){
123     e[++tot1].too=b,e[tot1].pre=last[a],last[a]=tot1;
124     e[++tot1].too=a,e[tot1].pre=last[b],last[b]=tot1;
125 }
126 int main(){
127     n=read(),m=read();
128     for(i=1;i<=n;i++)v[i]=read();
129     for(i=1;i<n;i++)insert(read(),read());
130     dfs(1),dfs2(1,1);int id,lca,a,b;
131 //  for(i=1;i<=n;i++)printf("%d  bel:%d\n",i,bel[i]);//return 233;
132     while(m--){
133         id=read(),a=read(),b=read(),lca=getlca(a,b);
134         if(id==1){
135             V=read();
136             if(!V)continue;
137             change(a,lca),change(b,lca);
138             L=R=pos[lca],insert(rt[bel[lca]],1,len[bel[lca]]);
139         }else{
140             SM=0;
141             query1(a,lca),query1(b,lca),
142             L=R=pos[lca],query(rt[bel[lca]],1,len[bel[lca]]);
143             printf("%lld\n",SM);
144         }//puts("");
145     }
146     return 0;
147 }
View Code

 

posted @ 2016-06-19 12:52  czllgzmzl  阅读(148)  评论(0编辑  收藏  举报