zoukankan      html  css  js  c++  java
  • [BZOJ4127]Abs

    [BZOJ4127]Abs

    题目大意:

    给你一棵(n(nle10^5))个结点的树,(m(mle10^5))个操作,操作共(2)种:

    1. (u,v)路径上的所有结点权值(+d(dle0))
    2. 询问(u,v)路径上所有结点权值的绝对值的和。

    思路:

    开两棵线段树,分别维护正数和负数。要维护区间和,如果是负数的话还要维护最大值。

    询问的时候如果负数的最大值(>0)了,就把它暴力弄进正数的线段树里面。

    由于每个数最多被暴力一次,总共(m)次操作,因此时间复杂度为(mathcal O((n+mlog n)log n))

    源代码:

    #include<cstdio>
    #include<cctype>
    #include<vector>
    #include<climits>
    inline int getint() {
    	register char ch;
    	register bool neg=false;
    	while(!isdigit(ch=getchar())) neg|=ch=='-';
    	register int x=ch^'0';
    	while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    	return neg?-x:x;
    }
    typedef long long int64;
    const int N=1e5+1;
    std::vector<int> e[N];
    inline void add_edge(const int &u,const int &v) {
    	e[u].push_back(v);
    	e[v].push_back(u);
    }
    int w[N],dep[N],par[N],top[N],size[N],son[N],dfn[N];
    void dfs(const int &x,const int &par) {
    	size[x]=1;
    	::par[x]=par;
    	dep[x]=dep[par]+1;
    	for(unsigned i=0;i<e[x].size();i++) {
    		const int &y=e[x][i];
    		if(y==par) continue;
    		dfs(y,x);
    		size[x]+=size[y];
    		if(size[y]>size[son[x]]) {
    			son[x]=y;
    		}
    	}
    }
    class SegmentTree {
    #define _left <<1
    #define _right <<1|1
    #define mid ((b+e)>>1)
    	private:
    		int64 val[N<<2],tag[N<<2],max[N<<2];
    		int cnt[N<<2];
    		void push_down(const int &p,const int &b,const int &e) {
    			if(tag[p]==0) return;
    			tag[p _left]+=tag[p];
    			tag[p _right]+=tag[p];
    			val[p _left]+=tag[p]*cnt[p _left];
    			val[p _right]+=tag[p]*cnt[p _right];
    			max[p _left]+=tag[p];
    			max[p _right]+=tag[p];
    			tag[p]=0;
    		}
    		void push_up(const int &p) {
    			val[p]=val[p _left]+val[p _right];
    			max[p]=INT_MIN;
    			if(cnt[p _left]) max[p]=std::max(max[p],max[p _left]);
    			if(cnt[p _right]) max[p]=std::max(max[p],max[p _right]);
    			cnt[p]=cnt[p _left]+cnt[p _right];
    		}
    		void update(const int &p,const int &b,const int &e);
    	public:
    		void modify(const int &p,const int &b,const int &e,const int &l,const int &r,const int64 &v,const int &t) {
    			if(b==l&&e==r) {
    				if(t) cnt[p]=1;
    				val[p]+=v*cnt[p];
    				max[p]+=v;
    				tag[p]+=v;
    				return;
    			}
    			push_down(p,b,e);
    			if(l<=mid) modify(p _left,b,mid,l,std::min(mid,r),v,t);
    			if(r>mid) modify(p _right,mid+1,e,std::max(mid+1,l),r,v,t);
    			push_up(p);
    		}
    		int64 query(const int &p,const int &b,const int &e,const int &l,const int &r,const int &t) {
    			if(b==l&&e==r) {
    				if(t==0&&max[p]>0) update(p,b,e);
    				return val[p];
    			}
    			int64 ret=0;
    			push_down(p,b,e);
    			if(l<=mid) ret+=query(p _left,b,mid,l,std::min(mid,r),t);
    			if(r>mid) ret+=query(p _right,mid+1,e,std::max(mid+1,l),r,t);
    			push_up(p);
    			return ret;
    		}
    };
    SegmentTree sgt[2];
    void SegmentTree::update(const int &p,const int &b,const int &e) {
    	if(max[p]<=0||cnt[p]==0) return;
    	if(b==e) {
    		sgt[1].modify(1,1,dfn[0],b,e,val[p],1);
    		val[p]=max[p]=cnt[p]=0;
    		return;
    	}
    	push_down(p,b,e);
    	update(p _left,b,mid);
    	update(p _right,mid+1,e);
    	push_up(p);
    }
    #undef _left
    #undef _right
    #undef mid
    void dfs(const int &x) {
    	dfn[x]=++dfn[0];
    	top[x]=x==son[par[x]]?top[par[x]]:x;
    	if(son[x]) dfs(son[x]);
    	for(unsigned i=0;i<e[x].size();i++) {
    		const int &y=e[x][i];
    		if(y==par[x]||y==son[x]) continue;
    		dfs(y);
    	}
    }
    inline void modify(int x,int y,const int &v) {
    	while(top[x]!=top[y]) {
    		if(dep[top[x]]<dep[top[y]]) std::swap(x,y);
    		sgt[0].modify(1,1,dfn[0],dfn[top[x]],dfn[x],v,0);
    		sgt[1].modify(1,1,dfn[0],dfn[top[x]],dfn[x],v,0);
    		x=par[top[x]];
    	}
    	if(dep[x]<dep[y]) std::swap(x,y);
    	sgt[0].modify(1,1,dfn[0],dfn[y],dfn[x],v,0);
    	sgt[1].modify(1,1,dfn[0],dfn[y],dfn[x],v,0);
    }
    inline int64 query(int x,int y) {
    	int64 ret=0;
    	while(top[x]!=top[y]) {
    		if(dep[top[x]]<dep[top[y]]) std::swap(x,y);
    		ret-=sgt[0].query(1,1,dfn[0],dfn[top[x]],dfn[x],0);
    		ret+=sgt[1].query(1,1,dfn[0],dfn[top[x]],dfn[x],1);
    		x=par[top[x]];
    	}
    	if(dep[x]<dep[y]) std::swap(x,y);
    	ret-=sgt[0].query(1,1,dfn[0],dfn[y],dfn[x],0);
    	ret+=sgt[1].query(1,1,dfn[0],dfn[y],dfn[x],1);
    	return ret;
    }
    int main() {
    	const int n=getint(),m=getint();
    	for(register int i=1;i<=n;i++) w[i]=getint();
    	for(register int i=1;i<n;i++) {
    		add_edge(getint(),getint());
    	}
    	dfs(1,0);
    	dfs(1);
    	for(register int i=1;i<=n;i++) {
    		sgt[0].modify(1,1,n,dfn[i],dfn[i],w[i],1);
    	}
    	for(register int i=0;i<m;i++) {
    		const int opt=getint(),u=getint(),v=getint();
    		if(opt==1) {
    			modify(u,v,getint());
    		}
    		if(opt==2) {
    			printf("%lld
    ",query(u,v));
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Leetcode 238. Product of Array Except Self
    Leetcode 103. Binary Tree Zigzag Level Order Traversal
    Leetcode 290. Word Pattern
    Leetcode 205. Isomorphic Strings
    Leetcode 107. Binary Tree Level Order Traversal II
    Leetcode 102. Binary Tree Level Order Traversal
    三目运算符
    简单判断案例— 分支结构的应用
    用switch判断月份的练习
    java基本打印练习《我行我素购物系统》
  • 原文地址:https://www.cnblogs.com/skylee03/p/9707178.html
Copyright © 2011-2022 走看看