zoukankan      html  css  js  c++  java
  • CodeChef 2020 November Challenge

    CodeChef 2020 November Challenge - Scalar Product Tree (莫队)

    题目大意:给定一棵根为1的树,每个点有权值(A_i),每个点按照其从根开始的路径记录下来一串数((A_1,cdots,A_u))构成一个向量(v_u)

    每次查询两个点((x,y)),查询(v_xcdot v_y)

    [ ]

    由于向量点积是对位相乘的,不好用数据结构维护

    考虑用一个序列描述( ext{dfs})遍历树时每个点入栈出栈的过程,扫描一段前缀即可得到遍历到每个点时( ext{dfs})栈的情况,也就得到了题目指定的向量

    每次查询两个点(x,y),那么就是查询了两段前缀,用莫队维护两个前缀指针的移动,同时维护每个深度上两个前缀对应的值以及这些值的乘积即可

    复杂度为(O(nsqrt n))

    #include<bits/stdc++.h>
    using namespace std;
    typedef pair <int,int> Pii;
    #define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i)
    #define drep(i,a,b) for(int i=a,i##end=b;i>=i##end;--i)
    
    char IO;
    template <class T=int> T rd(){
    	T s=0; int f=0;
    	while(!isdigit(IO=getchar())) f|=IO=='-';
    	do s=(s<<1)+(s<<3)+(IO^'0');
    	while(isdigit(IO=getchar()));
    	return f?-s:s;
    }
    
    const int N=6e5+10,P=1e9+7;
    
    int n,m;
    struct Edge{
    	int to,nxt;
    }e[N];
    int head[N],ecnt;
    void AddEdge(int u,int v) {
    	e[++ecnt]=(Edge){v,head[u]};
    	head[u]=ecnt;
    }
    int id[N],dfn;
    
    typedef unsigned U;
    U A[N];
    int L[N],K[N]; // L,K维护括号序列,L为编号,K为左括号还是右括号
    U Sum,Ans[N];
    int dep[N];
    
    void dfs(int u,int f) {
    	L[id[u]=++dfn]=u,K[dfn]=1;
    	dep[u]=dep[f]+1;
    	for(int i=head[u];i;i=e[i].nxt) {
    		int v=e[i].to;
    		if(v==f) continue;
    		dfs(v,u);
    	}
    	L[++dfn]=u,K[dfn]=-1;
    }
    
    int len;
    struct Que{
    	int l,r,id;
    	bool operator < (const Que __) const {
    		if(l/len!=__.l/len) return l/len<__.l/len;
    		return ((l/len)&1)?r<__.r:r>__.r;
    	}
    } Q[N];
    
    U S[2][N];
    void Add(int d,int x,int k) {
    	int p=dep[x];
    	Sum-=S[d][p]*S[!d][p];
    	S[d][p]=k==1?A[x]:0;
    	Sum+=S[d][p]*S[!d][p];
    }
    
    int main() {
    	n=rd(),m=rd();
    	rep(i,1,n) A[i]=rd();
    	rep(i,2,n) {
    		int u=rd(),v=rd();
    		AddEdge(u,v),AddEdge(v,u);
    	}
    	dfs(1,0),len=sqrt(dfn);
    	rep(i,1,m) {
    		int l=rd(),r=rd();
    		l=id[l],r=id[r];
    		if(l>r) swap(l,r);
    		Q[i]=(Que){l,r,i};
    	}
    	sort(Q+1,Q+m+1);
    	int l=1,r=1;
    	Add(0,1,1),Add(1,1,1);
    	rep(i,1,m) {
    		while(l<Q[i].l) ++l,Add(0,L[l],K[l]);
    		while(l>Q[i].l) Add(0,L[l],-K[l]),l--;
    		
    		while(r<Q[i].r) ++r,Add(1,L[r],K[r]);
    		while(r>Q[i].r) Add(1,L[r],-K[r]),r--;
    		Ans[Q[i].id]=Sum;
    	}
    	rep(i,1,m) printf("%u
    ",Ans[i]);
    }
    
  • 相关阅读:
    light oj 1205
    light oj 1068
    10月29日 小小犇的流水账
    小奇的数列
    10月28日 小小犇的流水账
    10月27日 小小犇的流水账
    2018.10.27 搬砖题解
    10月26日 小小犇的流水账
    10月25日 小小犇的流水账
    10月24日 小小犇的流水账
  • 原文地址:https://www.cnblogs.com/chasedeath/p/13995638.html
Copyright © 2011-2022 走看看