zoukankan      html  css  js  c++  java
  • [LNOI2014]LCA

    [LNOI2014]LCA
    这道题难道不是数据结构水题吗 逃)
    首先想到一个i点的(dep)相当于根节点走到i 进过的点之和,所以这个点对答案的贡献就是从这个点走到根节点。因此我们可以转换为当前节点(i)到根节点所经过的所有节点权值++。
    显然可以用线段树+树链剖分的数据结构进行优化 对于每一个询问 建一颗权值线段树 存储当前区间(sum),(sum)存储的就是(sum)
    然后我们需要想到用 类似于前缀和的思想来进行优化
    例如 (l=2 ,r=4 ,z=4) 我们可以用前缀和的思想进行优化 计算(1到4)(sum)(-1到1的sum) 就可以得到答案了
    想到了前缀和 想到了树剖+线段树 如果每一次查询 你都要新建两次树
    那就会GG!
    因此我们又想到了莫队的思想,将询问区间的(l,r)排序(因为询问区间为(1到l)(1到r),左区间都是一样的,所以我们可以将l,r一起排序),然后一个一个的加点 这样就可以不用每一次询问都新建一颗树了

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #define int long long 
    using namespace std;
    const int mod=201314,maxn=100010;
    int n,q,tot,fa[maxn],cnt_q;
    int first[maxn],nxt[maxn<<1],to[maxn<<1],dep[maxn<<1],cnt_id;
    int id[maxn<<1],rk[maxn<<1],size[maxn<<1],son[maxn<<1],top[maxn<<1],now;
    int tag[maxn<<1],sum[maxn<<1];
    struct node{
    	int id,pos,z,flag;
    	inline bool operator <(const node &x)const{
    		return pos<x.pos || (x.pos==pos && id<x.id);
    	}
    }ques[maxn<<4];
    struct node1{
    	int ans1,ans2;
    }ans[maxn<<2];
    void dfs1(int x,int father){
    	size[x]=1;fa[x]=father;
    	for(int i=first[x];i;i=nxt[i]){
    		int y=to[i];if(y==father) continue;
    		dep[y]=dep[x]+1;
    		dfs1(y,x);size[x]+=size[y];
    		if(size[son[x]]<size[y])
    			son[x]=y;
    	}
    }
    void dfs2(int x,int topo){
    	id[x]=++cnt_id;rk[cnt_id]=x;top[x]=topo;
    	if(son[x])	dfs2(son[x],topo);
    	for(int i=first[x];i;i=nxt[i]){
    		int y=to[i];if(y==fa[y] || y==son[x]) continue;
    		dfs2(y,y);
    	}
    }
    void add(int x,int y){nxt[++tot]=first[x];first[x]=tot;to[tot]=y;}
    void tagg(int node,int l,int r,int ta)
    {
    	sum[node]=(sum[node]+(r-l+1)*ta)%mod;
    	if(l<r) tag[node]=(tag[node]+ta)%mod;	
    }
    void push_down(int node,int l,int r){
    	if(l<r && tag[node]){
    		int mid=(l+r)>>1;
    		tagg(node<<1,l,mid,tag[node]);
    		tagg(node<<1|1,mid+1,r,tag[node]);
    	}
    	tag[node]=0;
    }
    void push_up(int node){sum[node]=(sum[node<<1]+sum[node<<1|1])%mod;}
    void modify(int node,int l,int r,int ql,int qr){
    	if(qr<l || ql>r) return ;
    	if(ql<=l && r<=qr){
    		tagg(node,l,r,1);
    		return ;
    	}
    	push_down(node,l,r);
    	int mid=(l+r)>>1;
    	modify(node<<1,l,mid,ql,qr);modify(node<<1|1,mid+1,r,ql,qr);
    	push_up(node);
    }
    void line_modify(int x,int y){
    	int tx=top[x],ty=top[y];
    	while(tx!=ty){
    		if(dep[tx]<dep[ty]){
    			x^=y^=x^=y;tx^=ty^=tx^=ty;
    		}
    		modify(1,1,n,id[tx],id[x]);
    		x=fa[tx];tx=top[x];
    	}
    	if(dep[x]<dep[y])
    		x^=y^=x^=y;
    	modify(1,1,n,id[y],id[x]);
    }
    int query(int node,int l,int r,int ql,int qr){
    	if(ql<=l && r<=qr)	return (sum[node]%mod);
    	push_down(node,l,r);
    	int mid=(l+r)>>1,anss=0;
    	if(ql<=mid)	anss+=query(node<<1,l,mid,ql,qr);
    	if(mid<qr) anss+=query(node<<1|1,mid+1,r,ql,qr);
    	return anss%mod;
    }
    int line_query(int x,int y){
    	int tx=top[x],ty=top[y],anss=0;
    	while(tx!=ty){
    		if(dep[tx]<dep[ty]){
    			x^=y^=x^=y;tx^=ty^=tx^=ty;
    		}
    		anss+=query(1,1,n,id[tx],id[x]);
    		anss%=mod;
    		x=fa[tx];tx=top[x];
    	}
    	if(dep[x]<dep[y])
    		x^=y^=x^=y;
    	anss+=query(1,1,n,id[y],id[x]);
    	return anss%mod;
    }
    signed main(){
    	scanf("%lld %lld",&n,&q);
    	for(int i=2,x;i<=n;i++){
    		scanf("%lld",&x);add(++x,i);
    	}
    		
    	dep[1]=1;
    	dfs1(1,0);dfs2(1,1);
    	for(int i=1,l,r,z;i<=q;i++){
    		 scanf("%lld %lld %lld",&l,&r,&z);r++;z++;
    		 ques[++cnt_q]=((node){i,l,z,0});ques[++cnt_q]=((node){i,r,z,1});
    	}
    	sort(ques+1,ques+1+cnt_q);now=0;
    	for(int i=1;i<=cnt_q;i++){
    		while(now<ques[i].pos)
    			line_modify(1,++now);
    		int num=ques[i].id;
    		if(ques[i].flag==1)	ans[num].ans1=line_query(1,ques[i].z);
    		else ans[num].ans2 =line_query(1,ques[i].z);
    	}
    	for(int i=1;i<=q;i++)
    		printf("%lld
    ",(ans[i].ans1-ans[i].ans2+mod)%mod);
    	return 0;
    }
    
  • 相关阅读:
    Windows批处理方式实现MySQL定期自动备份多个数据库
    MySQL数据库中库、表名、字段的大小写问题
    使用modbus4j通过串口解析modbus协议(java)
    mybatis —— 动态sql之if条件判断各种使用方式
    Mysql 获取表的comment 字段
    [转载]如何判断数据库,表或字段是否存在
    设计模式目录
    图片上传及访问
    实现第一个API
    ListView 源码解析
  • 原文地址:https://www.cnblogs.com/mendessy/p/11738893.html
Copyright © 2011-2022 走看看