您的位置:首页 > 其它

[bzoj4127] Abs

2016-06-19 12:52 363 查看
  链剖。线段树要记录区间内负数的个数,负数的最大值..

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

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

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
#define ll long long
using namespace std;
const int maxn=100233;
struct zs{
int too,pre;
}e[maxn<<1];int tot1,last[maxn];
int lc[maxn<<1],rc[maxn<<1],sz[maxn<<1],mx[maxn<<1],num[maxn<<1],tot;
ll sm[maxn<<1],add[maxn<<1],V,SM;
int dfn[maxn],tim,st[maxn],top,pos[maxn],bel[maxn],v[maxn],sz1[maxn],dep[maxn],fa[maxn],len[maxn],rt[maxn];
int i,j,k,n,m,L,R;

int ra,fh;char rx;
inline int read(){
rx=getchar(),ra=0,fh=1;
while((rx<'0'||rx>'9')&&rx!='-')rx=getchar();
if(rx=='-')fh=-1,rx=getchar();
while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra*fh;
}

inline void upd(int x){
int l=lc[x],r=rc[x];
if(mx[l]==-1e9)mx[x]=mx[r]+add[r];else
if(mx[r]==-1e9)mx[x]=mx[l]+add[l];else mx[x]=max(mx[l]+add[l],mx[r]+add[r]);
if(mx[x]>=0)mx[x]=-1e9;
sm[x]=sm[l]+sm[r],num[x]=num[l]+num[r];
}
inline void pushdown(int x){
int l=lc[x],r=rc[x];
if(mx[l]==-1e9)sm[l]+=add[x]*sz[l];
else sm[l]+=add[x]*(sz[l]-num[l]-num[l]);
if(mx[r]==-1e9)sm[r]+=add[x]*sz[r];
else sm[r]+=add[x]*(sz[r]-num[r]-num[r]);
add[l]+=add[x],add[r]+=add[x],
add[x]=0;
}
void build(int a,int b){
int x=++tot;sz[x]=b-a+1;
if(a==b){
sm[x]=abs(v[st[a]]);
if(v[st[a]]<0)mx[x]=v[st[a]],num[x]=1;else mx[x]=-1e9;
return;
}
int mid=a+b>>1;
lc[x]=tot+1,build(a,mid),rc[x]=tot+1,build(mid+1,b);
upd(x);
//  printf("  %d--%d sm:%lld mx:%d\n",a,b,sm[x],mx[x]);
}
void insert(int x,int a,int b){
if(L<=a&&R>=b){
if(mx[x]==-1e9){sm[x]+=V*sz[x],add[x]+=V;return;}
if(mx[x]+add[x]+V<0){sm[x]+=V*(sz[x]-num[x]-num[x]),add[x]+=V;return;}
}

if(a==b){
//      printf("! %d %d\n",a,mx[x]);
if(mx[x]+add[x]+V>=0)sm[x]=mx[x]+add[x]+V,mx[x]=-1e9,add[x]=num[x]=0;
else add[x]+=V,sm[x]-=V;
//      printf("  %d %lld\n",mx[x],sm[x]);
return;
}
if(add[x])pushdown(x);
int mid=a+b>>1;
if(L<=mid)insert(lc[x],a,mid);
if(R>mid)insert(rc[x],mid+1,b);
upd(x);
//  printf("ins:  %d--%d  sm:%lld mx:%d  num:%d\n",a,b,sm[x],mx[x],num[x]);
}
void query(int x,int a,int b){
if(L<=a&&R>=b){SM+=sm[x];/*printf("%d--%d    %lld\n",a,b,sm[x]);*/return;}
if(add[x])pushdown(x);
int mid=a+b>>1;
if(L<=mid)query(lc[x],a,mid);
if(R>mid)query(rc[x],mid+1,b);
upd(x);
}

void dfs(int x){
sz1[x]=1,dep[x]=dep[fa[x]]+1;
for(int i=last[x];i;i=e[i].pre)if(e[i].too!=fa[x])
fa[e[i].too]=x,dfs(e[i].too),sz1[x]+=sz1[e[i].too];
}
void dfs2(int x,int chain){
int mx=0,i;
dfn[x]=++tim,pos[x]=tim-dfn[chain]+1,
bel[x]=chain,st[++top]=x;
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;
if(!mx){
len[chain]=pos[x],rt[chain]=tot+1,build(1,top),top=0;
return;
}else dfs2(mx,chain);
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);
}
inline int getlca(int a,int b){
if(dep[bel[a]]<dep[bel[b]])swap(a,b);
while(bel[a]!=bel[b]){
a=fa[bel[a]];
if(dep[bel[a]]<dep[bel[b]])swap(a,b);
}
return dep[a]<dep[b]?a:b;
}

void change(int a,int lca){
while(bel[a]!=bel[lca]){
L=1,R=pos[a],insert(rt[bel[a]],1,len[bel[a]]);
a=fa[bel[a]];
}
if(a!=lca)L=pos[lca]+1,R=pos[a],insert(rt[bel[a]],1,len[bel[a]]);
}
void query1(int a,int lca){//printf("Q %d %d\n",a,lca);
while(bel[a]!=bel[lca]){
L=1,R=pos[a],query(rt[bel[a]],1,len[bel[a]]);
a=fa[bel[a]];
}
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]]);
}
inline void insert(int a,int b){
e[++tot1].too=b,e[tot1].pre=last[a],last[a]=tot1;
e[++tot1].too=a,e[tot1].pre=last[b],last[b]=tot1;
}
int main(){
n=read(),m=read();
for(i=1;i<=n;i++)v[i]=read();
for(i=1;i<n;i++)insert(read(),read());
dfs(1),dfs2(1,1);int id,lca,a,b;
//  for(i=1;i<=n;i++)printf("%d  bel:%d\n",i,bel[i]);//return 233;
while(m--){
id=read(),a=read(),b=read(),lca=getlca(a,b);
if(id==1){
V=read();
if(!V)continue;
change(a,lca),change(b,lca);
L=R=pos[lca],insert(rt[bel[lca]],1,len[bel[lca]]);
}else{
SM=0;
query1(a,lca),query1(b,lca),
L=R=pos[lca],query(rt[bel[lca]],1,len[bel[lca]]);
printf("%lld\n",SM);
}//puts("");
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: