首页 > 其他分享 >TJ -「HNOI2015」开店

TJ -「HNOI2015」开店

时间:2024-02-04 19:15:35浏览次数:24  
标签:return int ll tree TJ 开店 HNOI2015 ans dis

TJ - 「HNOI2015」开店(洛谷)

一,题意

给你一棵\(n\)个节点的树,点有点权,边有边权,\(Q\)次询问每次让你求解点权在\(L\)到\(R\)之间的点到点\(u\)的距离和。(强制在线)

数据范围:\(n\le 1.5\times10^5,Q\le2\times10^5\)


二,思路

首先,我们先看弱化版,假设没有年龄的限制,看单个询问,设\(dis_i\)表示点\(i\)到根节点的路径上的和。题目就是求:

\[\sum_{i=l}^rdis_i+dis_u-2\times dis_{lca(i,u)}前面两项好求,关键是我们如何求解出$dis_{lca(i,u)}$呢? \]

其实我们发现,\(lca(i,u)\)到根节点的路径其实就是\(i,u\)到根节点的路径的重合的部分。

那么,我们考虑先将\(i\in[l,r]\)到根节点的路径上的边打上一个标记,(每个\(i\)都给其经过的边每条的标记+1),最后再让\(u\)往根节点走,\(dis_{lca(i,u)}\)就是路径上每个边的标记数量乘上此边权的和。

其实这个过程可以用树链剖分来解决。

但是呢,由于有年龄限制,我们可以将线段树改为主席树,在按照年龄对\(n\)个点排序后,每个点都开一新的,每次答案做差即可。

不过由于有多个区间修改,空间可能会爆炸,我们需要搞一个标记永久化。

请注意代码细节。


三,代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=15e4+5;
int n,Q;
ll A;
vector<int> V;//用来对年龄进行离散化
inline int get_id(int x){
	return lower_bound(V.begin(),V.end(),x)-V.begin()+1;
} 
//建图: 
struct edge{
	int v,nt;
	ll w;
}a[N*2];
int head[N],at;
inline void add(int u,int v,ll w){
	a[++at].v=v,a[at].nt=head[u],head[u]=at,a[at].w=w;
}

struct node{
	int val;
	int id;
}age[N];//年龄 (点权)
ll dis[N];//点i到根节点的路径上的权值和 
ll val[N],sum[N];//第i个点的父亲边的边权 ,dis数组排序后的前缀和 
bool cmp(node x,node y){
	return x.val<y.val;
}
//第一次dfs求解的树剖的东西: 
int son[N],deep[N],fa[N],siz[N];
void dfs1(int u,int dad){
	deep[u]=deep[dad]+1,fa[u]=dad,siz[u]=1;
	int v;
	ll w;
	for(int i=head[u];i;i=a[i].nt){
		v=a[i].v,w=a[i].w;
		if(v==dad) continue;
		dis[v]=dis[u]+w,val[v]=w;
		dfs1(v,u);
		if(siz[son[u]]<siz[v]) son[u]=v;
		siz[u]+=siz[v];
	}
}
//第二次dfs求解的树剖的东西:
int id[N],rev[N],top[N],dfn;
void dfs2(int u){
	id[u]=++dfn,rev[dfn]=u;
	if(son[u]){
		top[son[u]]=top[u];
		dfs2(son[u]);
	}
	int v;
	for(int i=head[u];i;i=a[i].nt){
		v=a[i].v;
		if(id[v]) continue;
		top[v]=v;
		dfs2(v);
	}
}
//主席树: 
int root[N],tot=0;
struct Segment_tree{
	int l,r;
	ll sum,lazy,ans;//sum表示这个区间内本来的边权和,lazy为永久化标记,ans为区间的和 
}tree[N*52];
int build(int l,int r){
	int p=++tot;
	if(l==r){
		tree[p].sum=val[rev[l]];
		return p;
	}
	int mid=(l+r)>>1;
	tree[p].l=build(l,mid);
	tree[p].r=build(mid+1,r);
	tree[p].sum=tree[tree[p].l].sum+tree[tree[p].r].sum;
	return p;
}
int insert(int pre,int l,int r,int x,int y){
	int p=++tot;
	tree[p]=tree[pre];
	if(x<=l&&r<=y){
		tree[p].lazy++;
		tree[p].ans+=tree[p].sum;
		return p;
	}
	int mid=(l+r)>>1;
	if(x<=mid) tree[p].l=insert(tree[pre].l,l,mid,x,y);
	if(y>=mid+1) tree[p].r=insert(tree[pre].r,mid+1,r,x,y);
	tree[p].ans=tree[tree[p].l].ans+tree[tree[p].r].ans+tree[p].sum*tree[p].lazy;
	return p;
}
ll query(int p,int l,int r,int x,int y,ll add){
	if(x<=l&&r<=y) return tree[p].ans+tree[p].sum*add;
	int mid=(l+r)>>1;
	ll ans=0;
	add+=tree[p].lazy;
	if(x<=mid) ans+=query(tree[p].l,l,mid,x,y,add);
	if(y>=mid+1) ans+=query(tree[p].r,mid+1,r,x,y,add);
	return ans;
}
inline ll ask(int u,ll r){
	ll ans=sum[r]+r*dis[u],tmp=0;
	int x=u;
	int fx=top[x];
	while(fx!=1){
		tmp+=query(root[r],1,n,id[fx],id[x],0);
		x=fa[fx];
		fx=top[x];
	}
	tmp+=query(root[r],1,n,id[1],id[x],0);
	return ans-tmp*2;
}
int main(){
	//读入: 
	scanf("%d%d%lld",&n,&Q,&A);
	for(int i=1;i<=n;i++){
		scanf("%d",&age[i].val);
		V.push_back(age[i].val);
		age[i].id=i;
	}
	int u,v,w;
	for(int i=1;i<n;i++){
		scanf("%d%d%lld",&u,&v,&w);
		add(u,v,w);add(v,u,w);
	}
	//树链剖分: 
	dfs1(1,0);
	top[1]=1;
	dfs2(1);
	//预处理离散化等: 
	sort(V.begin(),V.end());
	sort(age+1,age+1+n,cmp);
	for(int i=1;i<=n;i++)sum[i]=sum[i-1]+dis[age[i].id];
	//建立主席树: 
	root[0]=build(1,n);
	int x,fx;
	for(int i=1;i<=n;i++){
		root[i]=root[i-1];
		x=age[i].id,fx=top[x];
		while(fx!=1){
			root[i]=insert(root[i],1,n,id[fx],id[x]);
			x=fa[fx];
			fx=top[x];
		}
		root[i]=insert(root[i],1,n,id[1],id[x]);
	}
	//求解: 
	ll ans=0,aa,bb,l,r;
	while(Q--){
		scanf("%d%lld%lld",&u,&aa,&bb);
		l=min((aa+ans)%A,(bb+ans)%A);
		r=max((aa+ans)%A,(bb+ans)%A);
		l=lower_bound(V.begin(),V.end(),l)-V.begin()+1;
		r=upper_bound(V.begin(),V.end(),r)-V.begin(); 
		ans=ask(u,r);
		if(l>1) ans-=ask(u,l-1);
		printf("%lld\n",ans);
	}
	return 0;
} 

标签:return,int,ll,tree,TJ,开店,HNOI2015,ans,dis
From: https://www.cnblogs.com/123456xwd/p/18006826

相关文章

  • 第17天:信息打点-语言框架&开发组件&FastJson&Shiro&Log4j&SpringBoot等
    框架:简单代码的一个整合库,如果使用框架就只需要学习使用框架调用即可如:文件上传功能是需要很多代码来实现的,框架把这个代码进行封封装,调用即可影响:如果采用框架开发,代码的安全性是取决于框架的过滤机制 #Python-开发框架-Django&FlaskDjango1、识别插件2、Set-Cookie:expi......
  • ztjdtj.py
    代码片#-*-coding:utf-8-*-"""计算涨停价和跌停价,给定品种和昨天收盘价.Parameters----------lc:前收盘价,浮点数stype:整型,optional证券品种(0=可转债,1=股票).Thedefaultis0.Returns-------None.使用举例:%runztjdtj.py100#......
  • 洛谷 P3976 [TJOI2015] 旅游
    这出题人语言表达能力真的感人……希望你们看完这篇题解后不要觉得我的语言表达能力和出题人不相上下。题目大意给定一棵有点权的树,每次询问从\(u\)到\(v\)的路径上后经过的点权减去先经过的点权的最大值,再把这条路径上所有点的点权加上一个给定的数。分析俗话说得好:如果......
  • ExtJS 页面单文件
    更新记录2024年1月31日初始化。ExtJS教程汇总:https://www.cnblogs.com/cqpanda/p/16328016.html页面单文件写法ExtJS用官方脚手架(SenchaCMD)生成页面,在默认情况下会生成三个文件(View、ViewController、ViewModel)。有些时候为了方便可以直接像VueJS一样只定义一个文件,可......
  • fastjson 1268-jdbc
    1268-jdbc复现靶场项目是https://github.com/lemono0/FastJsonParty版本{"@type":"java.lang.AutoCloseable"回包:{"timestamp":"2024-01-31T09:45:27.342+0000","status":500,"error":"InternalS......
  • TJ-CF1423K
    CF1423K首先,我们假设\(a>b\),设\(\gcd(a,b)=c,a=k_1\timesc,b=k_2\timesc\)则\(c\leb<a\)则是\(c,k_1,k_2\)构成一个三角形,且\(k_1>k_2(k_1>1)\)分类讨论:\(c\)为最大值\(c<k_1+k_2,c>k_1>k_2\)由于\(c,k_1,k_2\)都为正整数,也就是说只要\(c>2......
  • P3879 [TJOI2010] 阅读理解(水题)
    [TJOI2010]阅读理解题目描述英语老师留了N篇阅读理解作业,但是每篇英文短文都有很多生词需要查字典,为了节约时间,现在要做个统计,算一算某些生词都在哪几篇短文中出现过。输入格式第一行为整数N,表示短文篇数,其中每篇短文只含空格和小写字母。按下来的N行,每行描述一篇短文......
  • 二、nextjs API路由如何做好JWT登录鉴权、身份鉴权,joi字段校验,全局处理异常等(c-shoppi
    介绍在这篇文章中,我们将学习如何在C-Shopping电商开源项目中,基于Next.js14,处理所有API路由中添加身份验证和错误处理中间件的思路与实现。这篇文章中的代码片段取自我最近开源项目C-Shopping,完整的项目和文档可在https://github.com/huanghanzhilian/c-shopping地址查看。Next......
  • 二、nextjs API路由如何做好JWT登录鉴权、身份鉴权,joi字段校验,全局处理异常等(c-shoppi
    介绍在这篇文章中,我们将学习如何在C-Shopping电商开源项目中,基于Next.js14,处理所有API路由中添加身份验证和错误处理中间件的思路与实现。这篇文章中的代码片段取自我最近开源项目C-Shopping,完整的项目和文档可在https://github.com/huanghanzhilian/c-shopping地址查看。Next.js......
  • P4588 [TJOI2018] 数学计算
    题目描述小豆现在有一个数x,初始值为1。小豆有Q次操作,操作有两种类型:1m:将x变为×*m,并输出xmodM。2pos:将x变为x除以第pos次操作所乘的数(保证第pos次操作一定为类型1,对于每一个类型1的操作至多会被除一次),并输出xmodM。输入格式一共有t组输入。对于每一......