zoukankan      html  css  js  c++  java
  • LOJ#6073. 「2017 山东一轮集训 Day5」距离

    LOJ

    题意

    给了你一棵树,然后给每个点一个新标号,每次问旧标号的点(u,v)路径上的所有点对应的新标号点到旧标号点(K)的距离总和;

    题解

    这些一抹多的限制都可以转化为偏序问题,最后只需要一下求若干个点到某点(x)的距离和公式(ANS=dis[u]*t+sum_{i=1}^tdis[i]-dis[lca(u,i)]*2),做法跟HNOI开店那题几乎一样,存每条边多算了多少次,然后套主席树统计就行了;

    #include<bits/stdc++.h>
    #define Fst first
    #define Snd second
    #define RG register
    #define mp make_pair
    #define mem(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long LL;
    typedef long double LD;
    typedef unsigned int UI;
    typedef unsigned long long ULL;
    template<typename T> inline void read(T& x) {
    	char c = getchar();
    	bool f = false;
    	for (x = 0; !isdigit(c); c = getchar()) {
    		if (c == '-') {
    			f = true;
    		}
    	}
    	for (; isdigit(c); c = getchar()) {
    		x = x * 10 + c - '0';
    	}
    	if (f) {
    		x = -x;
    	}
    }
    template<typename T, typename... U> inline void read(T& x, U& ... y) {
    	read(x), read(y...);
    }
    const int N=2e5+10;
    int n,p,Q,type,size,TIME;
    int head[N],dep[N],top[N],w[N],P[N],num[N],son[N],fa[N],ID[N],X[N],Y[N],root[N],np[N];
    LL dis[N],sw[N],sum[N];
    struct Node {
    	int lo,ro,cnt;
    	LL sum;
    }Tr[N*150];
    struct Edge {
    	int to,last,w;
    	Edge () {}
    	Edge (int a,int b,int c) :to(a),last(b),w(c) {}
    }edge[N<<1];
    void ADD(int a,int b,int c) {
    	edge[++p]=Edge(b,head[a],c); head[a]=p;
    	edge[++p]=Edge(a,head[b],c); head[b]=p;
    }
    void DFS(int u) {
    	num[u]=1;
    	for(int i=head[u];i;i=edge[i].last) {
    		int v=edge[i].to;
    		if(v!=fa[u]) {
    			w[v]=edge[i].w; dis[v]=dis[u]+edge[i].w; fa[v]=u; dep[v]=dep[u]+1; DFS(v);
    			num[u]+=num[v];
    			if(num[son[u]]<num[v]) son[u]=v;
    		}
    	}
    }
    void SFD(int u,int topv) {
    	ID[u]=++TIME; np[TIME]=u; top[u]=topv;
    	if(!son[u]) return;
    	SFD(son[u],topv);
    	for(int i=head[u];i;i=edge[i].last) {
    		int v=edge[i].to;
    		if(!ID[v]) SFD(v,v);
    	}
    }
    void Modify(int l,int r,int &o,int ql,int qr) {
    	Tr[++size]=Tr[o]; o=size;
    	Tr[o].sum+=sw[qr]-sw[ql-1];
    	if(ql==l&&r==qr) {
    		++Tr[o].cnt;
    		return;
    	}
    	int mid=l+r>>1;
    	if(qr<=mid) Modify(l,mid,Tr[o].lo,ql,qr);
    	else if(ql>mid) Modify(mid+1,r,Tr[o].ro,ql,qr);
    	else Modify(l,mid,Tr[o].lo,ql,mid),Modify(mid+1,r,Tr[o].ro,mid+1,qr);
    }
    LL Query(int l,int r,int x,int y,int ql,int qr,int t) {
    	if(ql<=l&&r<=qr) {
    		return Tr[x].sum-Tr[y].sum+1ll*t*(sw[r]-sw[l-1]);
    	}
    	t+=Tr[x].cnt-Tr[y].cnt;
    	int mid=l+r>>1; LL res=0;
    	if(ql<=mid) res=Query(l,mid,Tr[x].lo,Tr[y].lo,ql,qr,t);
    	if(qr>mid) res+=Query(mid+1,r,Tr[x].ro,Tr[y].ro,ql,qr,t);
    	return res;
    }
    LL Get(int u,int v,int K) {
    	LL res=0; int cnt=0;
    	while(top[u]!=top[v]) {
    		if(dep[top[u]]<dep[top[v]]) swap(u,v);
    		res+=dis[K]*(dep[u]-dep[top[u]]+1)+sum[ID[u]]-sum[ID[top[u]]-1];
    		X[++cnt]=root[ID[u]]; Y[cnt]=root[ID[top[u]]-1];
    		u=fa[top[u]];
    	}
    	if(dep[u]<dep[v]) swap(u,v);
    	res+=dis[K]*(dep[u]-dep[v]+1)+sum[ID[u]]-sum[ID[v]-1];
    	X[++cnt]=root[ID[u]]; Y[cnt]=root[ID[v]-1];
    	LL t=0;
    	for(int i=1;i<=cnt;++i) {
    		int x=K;
    		while(x) {
    			t+=Query(1,n,X[i],Y[i],ID[top[x]],ID[x],0)<<1;
    			x=fa[top[x]];
    		}
    	}
    	return res-t;
    }
    int main() {
    //	ios::sync_with_stdio(false);
    #ifdef rua
    	freopen("GG.in","r",stdin);
    #endif
    	read(type,n,Q);
    	for(int i=1;i<n;++i) {
    		int u,v,w; read(u,v,w);
    		ADD(u,v,w);
    	}
    	DFS(1); SFD(1,1);
    	for(int i=1;i<=n;++i) read(P[i]);
    	for(int i=1;i<=n;++i) sum[i]=sum[i-1]+dis[P[np[i]]],sw[i]=sw[i-1]+w[np[i]];
    	for(int i=1;i<=n;++i) {
    		root[i]=root[i-1];
    		int u=P[np[i]];
    		while(u) {
    			Modify(1,n,root[i],ID[top[u]],ID[u]);
    			u=fa[top[u]];
    		}
    	}
    	LL lastANS=0; 
    	while(Q--) {
    		int u,v,K; read(u,v,K);
    		u^=lastANS; v^=lastANS, K^=lastANS;
    		printf("%lld
    ",lastANS=Get(u,v,K));
    		lastANS*=type;
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    用Metasploit破解Mysql用户名和密码
    利用Android的UXSS漏洞完成一次XSS攻击
    Kali linux渗透测试常用工具汇总2-渗透攻击
    Kali linux渗透测试常用工具汇总1
    phantomjs模拟登录
    javascript中的面向对象
    javascript中的闭包
    Python的高级特性11:拓展基本数据类型(dict)
    Python的高级特性10:无聊的@property
    Python的高级特性9:蹩脚的多态
  • 原文地址:https://www.cnblogs.com/ak12/p/10222161.html
Copyright © 2011-2022 走看看