• [LNOI2014]LCA


    考虑到\(dep\)等同于到根的点数。
    考虑把\([l,r]\)的点到根节点都打上1的标记,再查询\(z\)到根的权值即可。
    考虑如何不重的统计。
    那么就进行前缀和,并且从小到大加入,然后拆开一个询问的操作就可以。

    树剖加线段树,\(O(nlog^2n)\)

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define ll long long
    #define N 500005
    #define mod 201314
    
    ll n,m;
    
    ll cnt,head[N];
    
    struct P{
    	int to,next;
    }e[N << 2];
    
    inline void add(int x,int y){
    	e[++cnt].to = y;
    	e[cnt].next = head[x];
    	head[x] = cnt;
    }
    
    ll son[N],siz[N],fa[N],dep[N],top[N],dfn[N];
    
    inline void dfs(int u,int f){
    	dep[u] = dep[f] + 1;
    	fa[u] = f;
    	siz[u] = 1;
    	for(int i = head[u];i;i = e[i].next){
    		int v = e[i].to;
    		if(v == f)
    		continue;
    		dfs(v,u);
    		siz[u] += siz[v];
    		if(siz[v] > siz[son[u]])
    		son[u] = v;
    	}
    }
    
    ll dfncnt;
    
    inline void dfs2(int u,int t){
    	top[u] = t;
    	dfn[u] = ++dfncnt;
    	if(son[u])dfs2(son[u],t);
    	for(int i = head[u];i;i = e[i].next){
    		int v = e[i].to;
    		if(v == fa[u] || v == son[u] || v == 1)
    		continue;
    		dfs2(v,v);
    	}
    }
    
    //tree_cut__________
    
    ll s[N << 2],tag[N << 2];
    
    #define ls(x) (x << 1)
    #define rs(x) (x << 1 | 1)
    #define mid ((l + r) >> 1)
    
    inline void up(int u){
    	s[u] = (s[ls(u)] + s[rs(u)]) % mod;
    }
    
    inline void down(int u,int l,int r){
    	if(tag[u]){
    		tag[ls(u)] += tag[u];
    		s[ls(u)] += tag[u] * (mid - l + 1);	
    		s[ls(u)] %= mod;	
    		tag[rs(u)] += tag[u];
    		s[rs(u)] += tag[u] * (r - mid);	
    		s[rs(u)] %= mod;						
    		tag[u] = 0;
     	}
    }
    
    inline void change(int u,int l,int r,int tl,int tr,int p){
    //	std::cout<<u<<" "<<l<<" "<<r<<" "<<tl<<" "<<tr<<" "<<p<<std::endl;
    	if(tl <= l && r <= tr){
    		tag[u] += p;
    		s[u] += p * (r - l + 1);
    		s[u] %= mod;			
    		return ;
    	}
    	down(u,l,r);
    	if(tl <= mid)
    	change(ls(u),l,mid,tl,tr,p);
    	if(tr > mid)
    	change(rs(u),mid + 1,r,tl,tr,p);
    	up(u);
    }
    
    inline ll qi(int u,int l,int r,int tl,int tr){
    	ll ans = 0;
    //	std::cout<<l<<" "<<r<<" "<<tl<<" "<<tr<<" "<<s[u]<<std::endl;
    	if(tl <= l && r <= tr)
    	return s[u];
    	down(u,l,r);
    	if(tl <= mid)
    	ans += qi(ls(u),l,mid,tl,tr),ans %= mod;
    	if(tr > mid)
    	ans += qi(rs(u),mid + 1,r,tl,tr),ans %= mod;
    	return ans;
    }
    
    
    //______________________
    
    ll qcnt;
    
    struct d{
    	ll in,opt,id;
    }q[N];
    
    bool operator < (d a,d b){
    	return a.in < b.in;
    }
    
    ll final[N],ans[N];
    
    ll tp;
    
    inline void add(int x){
    //	std::cout<<"add"<<x<<":"<<std::endl;
    	while(dfn[top[x]] != dfn[1]){
    		change(1,1,n,dfn[top[x]],dfn[x],1);
    //		std::cout<<dfn[top[x]]<<" "<<dfn[x]<<std::endl;		
    		x = fa[top[x]];
    	}
    	change(1,1,n,dfn[1],dfn[x],1);
    //	std::cout<<dfn[1]<<" "<<dfn[x]<<std::endl;
    }
    
    inline void deal(int p){
    //	std::cout<<"deal"<<p<<":"<<std::endl;
    	int x = final[q[p].id];
    	ll f = 0;
    	while(dfn[top[x]] != dfn[1]){
    		f += qi(1,1,n,dfn[top[x]],dfn[x]);
    //		std::cout<<dfn[top[x]]<<" "<<dfn[x]<<" "<<f<<std::endl;
    		x = fa[top[x]];
    	}
    	f += qi(1,1,n,dfn[1],dfn[x]);
    //	std::cout<<dfn[1]<<" "<<dfn[x]<<" "<<f<<std::endl;
    	ans[q[p].id] = (ans[q[p].id] + q[p].opt * f + mod) % mod;
    }
    
    int main(){
    	scanf("%lld%lld",&n,&m);
    	for(int i = 2;i <= n;++i){
    		ll x;
    		scanf("%lld",&x);
    		x ++ ;
    		add(i,x);
    		add(x,i);
    	}
    	dfs(1,0);
    	dfs2(1,1);
    //	for(int i = 1;i <= n;++i){
    //		std::cout<<dfn[i]<<" "<<son[i]<<std::endl;
    //	}
    	for(int i = 1;i <= m;++i){
    		ll l,r,z;
    		scanf("%lld%lld%lld",&l,&r,&z);
    		l ++ ;
    		r ++ ;
    		z ++ ;
    		l -- ;
    		q[++qcnt].id = i;
    		q[qcnt].in = l;
    		q[qcnt].opt = -1;
    		q[++qcnt].id = i;
    		q[qcnt].in = r;
    		q[qcnt].opt = 1;
    		final[i] = z;
    	}
    	std::sort(q + 1,q + qcnt + 1);
    //	for(int i = 1;i <= qcnt;++i){
    //		std::cout<<q[i].in<<" "<<q[i].id<<" "<<q[i].opt<<std::endl;
    //	}
    	tp = 1;
    	while(q[tp].in == 0){
    		deal(tp);
    		tp ++ ;
    	}
    	for(int i = 1;i <= n;++i){
    		add(i);
    		while(q[tp].in == i){
    			deal(tp);
    			tp ++ ;
    		}
    	}
    	for(int i = 1;i <= m;++i)
    	std::cout<<ans[i]<<std::endl;
    }
    
  • 相关阅读:
    The first appliaction for "Hello World!"
    zone
    learn to study
    深入理解 Angular 2 变化监测和 ngZone
    看看吧
    生命周期钩子
    一个简单的todo
    依赖注入
    @Output()
    @Input
  • 原文地址:https://www.cnblogs.com/dixiao/p/15090710.html
Copyright © 2020-2023  润新知