zoukankan      html  css  js  c++  java
  • ACM-ICPC 2018 焦作赛区网络预赛 E. Jiu Yuan Wants to Eat


    分析

    除了树剖没想到其他解法。
    用线段树维护区间和,同时针对修改区间修改操作建立两个lazy标记,一个是(lazy_{mul}),另一个是(lazy_{add}),代表区间里的数都需要先乘以(lazy_{mul}),再加上(lazy_{add})。如果一个区间需要被重复标记,那么我们可以先把新的lazy标记施加在原有的lazy上。
    如果是区间乘以val,那么就可以$ lazy_{mul}=lazy_{mul} imes val,lazy_{add}=lazy_{add} imes val $
    对于区间取反操作可以转化成区间乘以-1,然后区间加上(2^{64}-1)

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef unsigned long long ll;
    const ll Mask=-1;
    const int maxn=100050;
    vector<int> G[maxn];
    int sz[maxn],son[maxn],top[maxn],fa[maxn];
    int dep[maxn];
    void dfs(int x,int par) {
    	sz[x]=1;
    	fa[x]=par;
    	for(auto y:G[x]) {
    		if(y!=par) {
    			dfs(y,x),sz[x]+=sz[y];
    			if(son[x]==0||sz[y]>sz[son[x]]) son[x]=y;
    		}
    	}
    }
    int L[maxn],R[maxn],idx[maxn],tot;
    void dfs2(int x,int par,int Top) {
    	dep[x]=dep[par]+1;
    	L[x]=++tot;
    	idx[tot]=x;
    	top[x]=Top;
    	if(son[x]) dfs2(son[x],x,Top);
    	for(auto y:G[x]) {
    		if(y!=par && y!=son[x]) {
    			dfs2(y,x,y);
    		}
    	}
    	R[x]=tot;
    }
    ll sum[maxn*4],lazy_mul[maxn*4],lazy_add[maxn*4],wid[maxn*4];
    void build(int l,int r,int id) {
    	lazy_mul[id]=1,lazy_add[id]=0;
    	wid[id]=r-l+1;
    	sum[id]=0;
    	if(l==r) return;
    	int mid=(l+r)>>1;
    	build(l,mid,id<<1);
    	build(mid+1,r,id<<1|1);
    }
    void pushDown(int id) {
    	if(wid[id]==1) {
    		lazy_mul[id]=1,lazy_add[id]=0;
    		return;
    	}
    	if(lazy_mul[id]==1&&lazy_add[id]==0) return;
    	int x=(id<<1);
    	lazy_mul[x]*=lazy_mul[id];
    	lazy_add[x]*=lazy_mul[id];
    	lazy_add[x]+=lazy_add[id];
    	sum[x]=sum[x]*lazy_mul[id]+(lazy_add[id]*wid[x]);
    
    	x=(id<<1|1);
    	lazy_mul[x]*=lazy_mul[id];
    	lazy_add[x]*=lazy_mul[id];
    	lazy_add[x]+=lazy_add[id];
    	sum[x]=sum[x]*lazy_mul[id]+(lazy_add[id]*wid[x]);
    	lazy_mul[id]=1;
    	lazy_add[id]=0;
    }
    void pushUp(int id) {
    	sum[id]=sum[id<<1]+sum[id<<1|1];
    }
    void mul_update(int x,int y,ll val,int l,int r,int id) {
    	pushDown(id);
    	if(x<=l && y>=r) {
    		lazy_mul[id]*=val;
    		lazy_add[id]*=val;
    		sum[id]*=val;
    		return;
    	}
    	int mid=(l+r)>>1;
    	if(x<=mid) mul_update(x,y,val,l,mid,id<<1);
    	if(y>mid) mul_update(x,y,val,mid+1,r,id<<1|1);
    	pushUp(id);
    }
    void add_update(int x,int y,ll val,int l,int r,int id) {
    	pushDown(id);
    	if(x<=l && y>=r) {
    		lazy_add[id]+=val;
    		sum[id]+=val*wid[id];
    		return;
    	}
    	int mid=(l+r)>>1;
    	if(x<=mid) add_update(x,y,val,l,mid,id<<1);
    	if(y>mid) add_update(x,y,val,mid+1,r,id<<1|1);
    	pushUp(id);
    }
    ll query(int x,int y,int l,int r,int id) {
    	// cout<<l<<" "<<r<<" "<<sum[id]<<endl;
    	pushDown(id);
    	if(x<=l && y>=r) {
    		//cout<<"in!
    ";
    		return sum[id];
    	}
    	int mid=(l+r)>>1;
    	ll ans=0;
    	if(x<=mid) /*(cout<<"go left
    ",*/ ans+=query(x,y,l,mid,id<<1);
    	if(y>mid) /*cout<<"go right
    ",*/ ans+=query(x,y,mid+1,r,id<<1|1);
    	return ans;
    }
    int main() {
    	int n,q;
    	while(scanf("%d", &n)!=EOF) {
    		build(1,n,1);
    		for(int i = 1; i <= n; ++i) G[i].clear(),sz[i]=top[i]=son[i]=0;
    		for(int i = 2; i <= n; ++i) {
    			int x;
    			scanf("%d", &x);
    			G[x].push_back(i);
    		}
    		scanf("%d", &q);
    		tot=0;
    		dfs(1,1);
    		dfs2(1,1,1);
    		while(q--) {
    			int t,x,y;
    			scanf("%d%d%d", &t,&x,&y);
    			ll val;
    			if(t==1) {
    				scanf("%llu", &val);
    				while(top[x]!=top[y]) {
    					if(dep[top[x]]<dep[top[y]]) swap(x,y);
    					mul_update(L[top[x]],L[x],val,1,n,1);
    					x=fa[top[x]];
    				}
    				if(L[x]>L[y]) swap(x,y);
    				mul_update(L[x],L[y],val,1,n,1);
    			}
    			else if(t==2) {
    				scanf("%llu", &val);
    				while(top[x]!=top[y]) {
    					if(dep[top[x]]<dep[top[y]]) swap(x,y);
    					add_update(L[top[x]],L[x],val,1,n,1);
    					x=fa[top[x]];
    				}
    				if(L[x]>L[y]) swap(x,y);
    				add_update(L[x],L[y],val,1,n,1);
    			}
    			else if(t==3) {
    				while(top[x]!=top[y]) {
    					if(dep[top[x]]<dep[top[y]]) swap(x,y);
    					mul_update(L[top[x]],L[x],-1,1,n,1);
    					add_update(L[top[x]],L[x],-1,1,n,1);
    					x=fa[top[x]];
    				}
    				if(L[x]>L[y]) swap(x,y);
    				mul_update(L[x],L[y],-1,1,n,1);
    				add_update(L[x],L[y],-1,1,n,1);
    			}
    			else {
    				ll ans=0;
    				while(top[x]!=top[y]) {
    					if(dep[top[x]]<dep[top[y]]) swap(x,y);
    					ans+=query(L[top[x]],L[x],1,n,1);
    					x=fa[top[x]];
    				}
    				if(L[x]>L[y]) swap(x,y);
    				ans+=query(L[x],L[y],1,n,1);
    				printf("%llu
    ", ans);
    			}
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    删除链表的倒数第N个节点(java实现)
    Java多线程之volatile关键字《一》
    Utils
    分布式和集群
    java RMIC
    Log4j输出终端(Appender)详解
    使用存储过程并返回值与及返回值的获得方法
    groupBy
    group by java实现
    本机Font字体
  • 原文地址:https://www.cnblogs.com/sciorz/p/9652204.html
Copyright © 2011-2022 走看看