zoukankan      html  css  js  c++  java
  • HDU 3966 树链剖分后线段树维护

    题意:

      一棵树,

      操作1.$path(a,b)$之间的点权$+k$

      操作2.单点查询

    题解:

    树链剖分即可,注意代码细节,双向映射

    主要是记录一下板子

    #include <string.h>
    #include <stdio.h>
    #include <algorithm>
    #define endl '
    '
    #define ll long long
    #define ull unsigned long long
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define all(x) x.begin(),x.end()
    #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
    #define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
    #define per(ii,a,b) for(int ii=b;ii>=a;--ii)
    #define forn(ii,x) for(int ii=head[x];ii;ii=edge[ii].next)
    using namespace std;
    const int maxn=5e4+20,maxm=2e6+10;
    const int INF=0x3f3f3f3f;
    const ll mod=1e9+7;
    //head
    int casn,n,m,k;
    int num[maxn];
    class segtree{public:
    #define nd node[now]
    #define ndl node[now<<1]
    #define ndr node[now<<1|1]
      int node[maxn*4],n;
      int *mp;
    	void maketree(int s,int t,int now){
    			if(s==t){
    				nd=num[mp[s]];
    				return ;
    			}else nd=0;
    			maketree(s,(s+t)/2,now<<1);
    			maketree((s+t)/2+1,t,now<<1|1);
    	}
    	void init(int nn,int *mps){
    		n=nn;mp=mps;
    		maketree(1,n,1);
    	}
    	void update(int s,int t,int x){
    		update(s,t,x,1,n,1);
    	}
    	int query(int pos){
    		return query(pos,1,n,1);
    	}
    	void update(int s,int t,int x,int l,int r,int now=1){
    			if(s<=l&&t>=r) {
    				nd+=x;
    				return ;
    			}
    			ndl+=nd,ndr+=nd;nd=0;
    			int mid=(l+r)/2;
    			if(s<=mid) update(s,t,x,l,mid,now<<1);
    			if(t>mid) update(s,t,x,mid+1,r,now<<1|1);
    	}
    	int query(int pos,int l,int r,int now=1){
    			if(l==r) return nd;
    			ndl+=nd,ndr+=nd;nd=0;
    			int mid=(l+r)/2;
    			if(pos<=mid) return query(pos,l,mid,now<<1);
    			else  return query(pos,mid+1,r,now<<1|1);
    	}
    }tree;
    namespace chain{
    	struct data_e{
    		int to,next;
    	}edge[maxn<<1];
    	int head[maxn],nume,mp[maxn];
    	inline void addedge(int a,int b){
    		edge[++nume]={b,head[a]};
    		head[a]=nume;
    	}
    	int ltop[maxn],fa[maxn],deep[maxn];
    	int sz[maxn],remp[maxn];
    	int son[maxn],cnt;
    	void init(){
        rep(i,1,n) head[i]=0;
        cnt=0,nume=1;
    	}
      void dfs1(int now,int pre,int d){
    		deep[now]=d,fa[now]=pre,sz[now]=1,son[now]=0;
    		forn(i,now){
    			int to=edge[i].to;
    			if(to!=pre) {
    				dfs1(to,now,d+1);
    				sz[now]+=sz[to];
    				if(sz[to]>sz[son[now]]) son[now]=to;
    			}
    		}
      }
      void dfs2(int now,int pre,int sp){
        ltop[now]=sp;mp[now]=++cnt;remp[cnt]=now;
    		if(son[now])  dfs2(son[now],now,sp);
    		forn(i,now){
    			int to=edge[i].to;
    			if(to!=son[now]&&to!=pre) dfs2(to,now,to);
    		}
      }
      void update(int a,int b,int val){
        while(ltop[a]!=ltop[b]){
    			if(deep[ltop[a]]<deep[ltop[b]])swap(a,b);
    			tree.update(mp[ltop[a]],mp[a],val);
    			a=fa[ltop[a]];
        }
    		if(deep[a]>deep[b])swap(a,b);
    		tree.update(mp[a],mp[b],val);
      }
    };
    
    int main() {
      while(~scanf("%d %d %d",&n,&m,&k)){
    		rep(i,1,n) scanf("%d",num+i);
    		chain::init();
        while(m--){
    			int a,b;scanf("%d%d",&a,&b);
    			chain::addedge(a,b);
    			chain::addedge(b,a);
        }
        chain::dfs1(1,0,1);
        chain::dfs2(1,1,1);
    		tree.init(n,chain::remp);
    		while(k--){
    			char x[10];int a,b,c;
    			scanf("%s",x);
    			if(x[0]=='Q'){
    				scanf("%d",&a);
    				printf("%d
    ",tree.query(chain::mp[a]));
    			}else if(x[0]=='I'){
    				scanf("%d %d %d",&a,&b,&c);
    				chain::update(a,b,c);
    			}else {
    				scanf("%d %d %d",&a,&b,&c);
    				chain::update(a,b,-c);
    			}
    		}
    	}
    }
    
  • 相关阅读:
    [PHP] Layui + jquery 实现 实用的文章自定义标签
    个人总结第五周
    个人总结第四周
    个人总结第三周
    个人总结第二周
    个人总结第一周
    用户体验评价
    第二阶段scrum冲刺
    单词统计
    用户模块和用户场景
  • 原文地址:https://www.cnblogs.com/nervendnig/p/10638239.html
Copyright © 2011-2022 走看看