zoukankan      html  css  js  c++  java
  • 题解 P6453 【[LNOI2014]LCA】

    题目链接

    Solution [LNOI2014]LCA

    题目大意:给定一棵树,每次给定 (l,r,z),询问 (sum_{i=l}^{r}dep[LCA(i,z)])

    树链剖分


    分析:

    关键性质在于,从根到两个点的路径的交,等于从根到它们的 (LCA) 的路径。而一个点的深度,就相当于根到那个点的路径长度。

    因此原问题等价于每次对于 (x in [l,r]),将根到 (x) 的路径加 (1),然后询问根到 (z) 的路径上的权值之和。

    这个可以离线下来,变成将 (x in [1,k]) 的路径加 (1),做个差分就可以了。

    直接树剖加上线段树维护。

    #include <cstdio>
    #include <cctype>
    #include <vector>
    #pragma GCC optmize(2)
    using namespace std;
    typedef long long ll;
    constexpr int maxn = 5e4 + 100,inf = 0x7fffffff,mod = 201314;
    inline int add(const int a,const int b){return (a + b) % mod;}
    inline int sub(const int a,const int b){return (a - b + mod) % mod;}
    inline int mul(const int a,const int b){return (1ll * a * b) % mod;}
    struct IO{//-std=c++11,with cstdio and cctype
    	private:
    		static constexpr int ibufsiz = 1 << 20;
    		char ibuf[ibufsiz + 1],*inow = ibuf,*ied = ibuf;
    		static constexpr int obufsiz = 1 << 20;
    		char obuf[obufsiz + 1],*onow = obuf;
    		const char *oed = obuf + obufsiz;
    	public:
    		inline char getchar(){
    			#ifndef ONLINE_JUDGE
    				return ::getchar();
    			#else
    				if(inow == ied){
    					ied = ibuf + sizeof(char) * fread(ibuf,sizeof(char),ibufsiz,stdin);
    					*ied = '';
    					inow = ibuf;
    				}
    				return *inow++;
    			#endif
    		}
    		template<typename T>
    		inline void read(T &x){
    			static bool flg;flg = 0;
    			x = 0;char c = getchar();
    			while(!isdigit(c))flg = c == '-' ? 1 : flg,c = getchar();
    			while(isdigit(c))x = x * 10 + c - '0',c = getchar();
    			if(flg)x = -x;
    		}
    		template <typename T,typename ...Y>
    		inline void read(T &x,Y&... X){read(x);read(X...);}
    		inline int readi(){static int res;read(res);return res;}
    		inline long long readll(){static long long res;read(res);return res;}
    		
    		inline void flush(){
    			fwrite(obuf,sizeof(char),onow - obuf,stdout);
    			fflush(stdout);
    			onow = obuf;
    		}
    		inline void putchar(char c){
    			#ifndef ONLINE_JUDGE
    				::putchar(c);
    			#else
    				*onow++ = c;
    				if(onow == oed){
    					fwrite(obuf,sizeof(char),obufsiz,stdout);
    					onow = obuf;
    				}
    			#endif
    		}
    		template <typename T>
    		inline void write(T x,char split = ''){
    			static unsigned char buf[64];
    			if(x < 0)putchar('-'),x = -x;
    			int p = 0;
    			do{
    				buf[++p] = x % 10;
    				x /= 10;
    			}while(x);
    			for(int i = p;i >= 1;i--)putchar(buf[i] + '0');
    			if(split != '')putchar(split);
    		}
    		inline void lf(){putchar('
    ');}
    		~IO(){
    			fwrite(obuf,sizeof(char),onow - obuf,stdout);
    		}
    }io;
    template <typename A,typename B>
    inline void chkmin(A &x,const B &y){if(y < x)x = y;}
    template <typename A,typename B>
    inline void chkmax(A &x,const B &y){if(y > x)x = y;}
    
    int n,q,ans[maxn];
    namespace st{
    	#define ls (rt << 1)
    	#define rs (rt << 1 | 1)
    	struct node{
    		int sum,add;
    	}tr[maxn << 2];
    	inline int calc(const int l,const int r){return r - l + 1;}
    	inline void pushup(const int rt){tr[rt].sum = add(tr[ls].sum,tr[rs].sum);}
    	inline void pushdown(const int rt,const int l,const int r){
    		tr[ls].add = add(tr[ls].add,tr[rt].add);
    		tr[rs].add = add(tr[rs].add,tr[rt].add);
    		int mid = (l + r) >> 1;
    		tr[ls].sum = add(tr[ls].sum,mul(calc(l,mid),tr[rt].add));
    		tr[rs].sum = add(tr[rs].sum,mul(calc(mid + 1,r),tr[rt].add));
    		tr[rt].add = 0;
    	}
    	inline void modify(const int a,const int b,const int v,const int l = 1,const int r = n,const int rt = 1){
    		if(a <= l && b >= r){
    			tr[rt].add = add(tr[rt].add,v);
    			tr[rt].sum = add(tr[rt].sum,mul(calc(l,r),v));
    			return;
    		}
    		pushdown(rt,l,r);
    		const int mid = (l + r) >> 1;
    		if(a <= mid)modify(a,b,v,l,mid,ls);
    		if(b >= mid + 1)modify(a,b,v,mid + 1,r,rs);
    		pushup(rt);
    	}
    	inline int query(const int a,const int b,const int l = 1,const int r = n,const int rt = 1){
    		if(a <= l && b >= r)return tr[rt].sum;
    		pushdown(rt,l,r);
    		int mid = (l + r) >> 1,res = 0;
    		if(a <= mid)res += query(a,b,l,mid,ls);
    		if(b >= mid + 1)res += query(a,b,mid + 1,r,rs);
    		return res % mod;
    	}
    	#undef ls
    	#undef rs
    }
    
    namespace tree{
    	vector<int> G[maxn];
    	inline void addedge(int u,int v){
    		// io.write(u,' '),io.write(v,'
    ');
    		G[u].push_back(v);}
    	int dfs_tot,dfn[maxn],rnk[maxn],dep[maxn],siz[maxn],son[maxn],top[maxn],faz[maxn];
    	inline void dfs1(const int u){
    		siz[u] = 1;
    		for(int v : G[u]){
    			dep[v] = dep[u] + 1;
    			dfs1(v);
    			siz[u] += siz[v];
    			if(siz[v] > siz[son[u]])son[u] = v;
    		}
    	}
    	inline void dfs2(const int u,const int tp){
    		dfn[u] = ++dfs_tot;
    		rnk[dfs_tot] = u;
    		top[u] = tp;
    		if(son[u])dfs2(son[u],tp);
    		for(int v : G[u]){
    			if(v == son[u])continue;
    			dfs2(v,v);
    		}
    	}
    	inline void modify(int u,const int v){
    		while(u){
    			st::modify(dfn[top[u]],dfn[u],v);
    			u = faz[top[u]];
    		}
    	}
    	inline int query(int u){
    		int res = 0;
    		while(u){
    			res = add(res,st::query(dfn[top[u]],dfn[u]));
    			u = faz[top[u]];
    		}
    		return res;
    	}
    }
    struct oper{
    	int id,z,flg;
    };
    vector<oper> vec[maxn];
    int main(){
    #ifndef ONLINE_JUDGE
    	freopen("fafa.in","r",stdin);
    #endif
    	tree::dep[1] = 1;
    	io.read(n,q);
    	for(int i = 2;i <= n;i++)
    		tree::faz[i] = io.readi() + 1,tree::addedge(tree::faz[i],i);
    	tree::dfs1(1);
    	tree::dfs2(1,1);
    	for(int l,r,z,i = 1;i <= q;i++){
    		io.read(l,r,z);l++,r++,z++;
    		vec[l - 1].push_back(oper{i,z,-1});
    		vec[r].push_back(oper{i,z,1});
    	}
    	for(int i = 1;i <= n;i++){
    		tree::modify(i,1);
    		for(auto it : vec[i])
    			if(it.flg == 1)ans[it.id] = add(ans[it.id],tree::query(it.z));
    			else ans[it.id] = sub(ans[it.id],tree::query(it.z));
    	}
    	for(int i = 1;i <= q;i++)io.write(ans[i],'
    ');
    	return 0;
    } 	
    
  • 相关阅读:
    网络和笔记本
    病毒惹的祸
    Virtual MachineVmware(2)
    VS2010 工具箱装载出错
    Virtual Machine VmWare(1)
    javascript写计数器
    代码自动生成操作
    用live writer写博客
    上海招聘.net程序员
    将用户导入到membership
  • 原文地址:https://www.cnblogs.com/colazcy/p/14062168.html
Copyright © 2011-2022 走看看