首页 > 其他分享 >P3714 [BJOI2017] 树的难题

P3714 [BJOI2017] 树的难题

时间:2024-03-19 22:16:08浏览次数:28  
标签:难题 le int siz void BJOI2017 P3714 ch long

from xcs

题意:

给定一棵 \(n\) 个节点的树,树根为 \(1\),每个点有一个编号,每条边有一个边权。

定义 \(dep(x)\) 表示一个点到根简单路径上边权的和,\(lca(x,y)\) 表示 \(x,y\) 节点在树上的最近公共祖先。

共 \(m\) 组询问,每次询问给出 \(l,r\),求对于所有点编号的二元组 \((i,j)\) 满足 \(l \le i,j \le r\) ,有多少种不同的 \(dep( lca(i,j))\)。

\(1\le n \le 10^5\),\(1\le m \le 5 \times 10^5\),所有数值为整数,\(-10^9 \le d \le 10^9\)。

分析:

显然需要在 LCA 处(记作 \(x\))统计答案,对于 \(u,v\),它们的 LCA 为 \(x\) 当且仅当,\(u,v\) 在 \(x\) 不同的子树内。暴力遍历两个不同的子树有效点对仍是 \(n^2\) 的。

考虑去掉一些一定不优的点对。假设存在两个点对 \((u_{1},v_{1})\) 和 \((u_{2},v_{2})\) 满足 \(u_{1} \le u_{2} \le v_{2} \le v_{1}\),那么 \((u_{1},v_{2})\) 一定不优。

使用 dsu on tree,先算出重儿子的 set,遍历轻儿子的时候在 set 里找一个前驱后继即可,跑完一个子树,就把这个子树加入到 set 里。由这个做法可以推断出有效的点对的数量级是 \(n \log n\) 的。

现在问题变成了给定若干个区间 \([l, r] \ :w\),然后询问 \([l,r]\) 里包含的所有区间的 \(w\) 的不同个数。

直接扫描线即可。时间复杂度 \(O(n \log n^2+q)\)。

代码:

#include<bits/stdc++.h>
//#define int long long
#define N 500005
#define il inline
using namespace std;
namespace IO{
    char buff[1<<21],*p1=buff,*p2=buff;
    char getch(){
        return p1==p2&&(p2=((p1=buff)+fread(buff,1,1<<21,stdin)),p1==p2)?EOF:*p1++;
    }
    template<typename T>
    void read(T &x){
        char ch=getch();int fl=1;x=0;
        while(ch>'9'||ch<'0'){if(ch=='-')fl=-1;ch=getch();}
        while(ch<='9'&&ch>='0'){x=x*10+ch-48;ch=getch();}
        x*=fl;
    }
    template<typename T,typename ...Args>
    void read(T &x,Args& ...args){
        read(x);read(args...);
    }
    char obuf[1<<21],*p3=obuf;
    void putch(char ch){
        if(p3-obuf<(1<<21))*p3++=ch;
        else fwrite(obuf,p3-obuf,1,stdout),p3=obuf,*p3++=ch;
    }
    char ch[100];
    template<typename T>
    void write(T x){
        if(!x)return putch('0');
        if(x<0)putch('-'),x*=-1;
        int top=0;
        while(x)ch[++top]=x%10+48,x/=10;
        while(top)putch(ch[top]),top--;
    }
    template<typename T,typename ...Args>
    void write(T x,Args ...args){
        write(x);write(args...);
    }
    void flush(){fwrite(obuf,p3-obuf,1,stdout);}
}
using namespace IO;
int n, m, cnt;
long long dis[N];
int siz[N], son[N];
struct edge {
	int to, w;
};
struct node {
	int r, w;
};
vector<node>G[N];
vector<edge>p[N];
set<int>s;
void dfs(int x, int fa) {
	int Maxson = -1;
	siz[x] = 1;
	int Len = p[x].size();
	for(int i = 0; i < Len; i++) {
		int y = p[x][i].to;
		if(y == fa) continue;
		dis[y] = dis[x] + p[x][i].w;
		dfs(y, x);
		siz[x] += siz[y];
		if(siz[y] > Maxson) {
			Maxson = siz[y];
			son[x] = y;
		}
	}
}
int h[N], tot;
void Sol(int x, int fa, int W) {
	h[++tot] = x;
	auto L = s.lower_bound(x);
	auto R = L;
	if(L != s.begin()) {
		L--;
		int l = (*L);
		if(l <= x) G[l].push_back((node){x, W});
	}
	if(R != s.end()) {
		int r = (*R);
		if(x <= r) G[x].push_back((node){r, W});
	}
	int Len = p[x].size();
	for(int i = 0; i < Len; i++) {
		int y = p[x][i].to;
		if(y == fa) continue;
		Sol(y, x, W);
	}
}
void work(int x, int fa, bool opt) { //optè¡¨ç¤ºæ˜¯å¦åˆ é™¤
	int Len = p[x].size();
	for(int i = 0; i < Len; i++) {
		int y = p[x][i].to;
		if(y == son[x] || y == fa) continue;
		work(y, x, 1);
	}
	
	if(son[x]) work(son[x], x, 0);
	G[x].push_back((node){x, (int)dis[x]});
	s.insert(x);
	for(int i = 0; i < Len; i++) {
		int y = p[x][i].to;
		if(y == son[x] || y == fa) continue;
		tot = 0;
		Sol(y, x, dis[x]);
		for(int j = 1; j <= tot; j++) s.insert(h[j]);
	}
	if(opt) s.clear();
}
int c[N];
il void add(int x, int y) {
	for(int i = x; i <= n; i += (i & (-i))) c[i] += y;
}
il int query(int x) {
	int res = 0;
	for(int i = x; i; i -= (i & (-i))) res += c[i];
	return res;
}
struct ask {
	int r, id;
};
vector<ask>z[N];
long long b[N];
int Min[N], ans[N];
il void Hash() {
	for(int i = 1; i <= n; i++) b[i] = dis[i], Min[i] = n + 1;
	sort(b + 1, b + n + 1);
	int len = unique(b + 1, b + n + 1) - b - 1;
	for(int i = 1; i <= n; i++) dis[i] = lower_bound(b + 1, b + len + 1, dis[i]) - b;
}
signed main() {
	//freopen("tree.in", "r", stdin);
	//freopen("tree.out", "w", stdout);
	read(n, m);
	for(int i = 1, u, v, w; i < n; i++) {
		read(u, v, w);
		p[u].push_back((edge){v, w});
		p[v].push_back((edge){u, w});
	}
	dfs(1, 0);
	Hash();
	work(1, 0, 0);
	for(int i = 1, l, r; i <= m; i++) {
		read(l, r); 
		z[l].push_back((ask){r, i});
	}
	for(int l = n; l >= 1; l--) {
		for(int j = 0; j < G[l].size(); j++) {
			if(G[l][j].r <= Min[G[l][j].w] - 1) {
				add(G[l][j].r, 1);
				add(Min[G[l][j].w], -1);
				Min[G[l][j].w] = G[l][j].r;
			}
		}
		for(int j = 0; j < z[l].size(); j++) 
			ans[z[l][j].id] = query(z[l][j].r);
	}
	for(int i = 1; i <= m; i++) {
		write(ans[i]);
		putch('\n');
	}
	flush();
	return 0;
}
/*
5 1
1 2 2
1 3 2
3 4 3
1 5 1
1 3
*/

标签:难题,le,int,siz,void,BJOI2017,P3714,ch,long
From: https://www.cnblogs.com/xcs123/p/18084061

相关文章

  • 打造程序员“造星计划”—从容应对裁员难题
    用键盘,敲出灵动的字符;用鼠标,点出幸福的人生;用智慧,推敲缜密的逻辑;用灵感,推开想象的大门;用语言,谱出鲜活的程序;用自信,编出明天的精彩。程序员节,愿你成就精彩,乐享人生!。用键盘,敲出灵动的字符;用鼠标,点出幸福的人生;用智慧,推敲缜密的逻辑;用灵感,推开想象的大门;用语言,谱出鲜活的......
  • 华为OD机试Js - MELON的难题
    005MELON的难题前言:本专栏将持续更新互联网大厂机试真题,并进行详细的分析与解答,包含完整的代码实现,希望可以帮助到正在努力的你。关于大厂机试流程、面经、面试指导等,如有任何疑问,欢迎联系我,wechat:steven_moda;email:[email protected];备注:CSDN。题目描述MELON有一堆精......
  • P1379 八数码难题
    原题链接题解1:朴素广搜注意细节code1#include<bits/stdc++.h>usingnamespacestd;intpoi[4]={-3,1,-1,3};intmain(){strings;cin>>s;queue<string>q;map<string,int>rec;q.push(s);rec[s]=1;while(q.size())......
  • 破局数据分析滞后难题,赋能企业高速增长的指标管理解决方案
    指标是什么?业务发展过程中,企业内外部都会产生很多的业务数据,对这些数据进行采集、计算、落库、分析后,形成的统计结果称为指标。简单来说,指标是业务被拆解、量化后形成的数量特征,企业利用数据指标对业务进行精准的号脉,实现对业务的科学管理和有效优化。在我们对多家企业展开深入......
  • 什么是机械制造ERP?可以解决哪些难题
        市面上有各式各样的机械产品,这些形式各异的商品对应不同的质检标准、生产工艺、制造工序、规格等,并且在生产过程中还产生大量琐碎的业务数据。你是否还在烦恼不能实时掌握车间产能、班组负荷、产品实际成本、订单进度等?还在思考如何全面协调各类生产关系,提升生产效......
  • 一篇文章解决你的无线AP选型难题:从入门到精通
    无线网络覆盖项目中,无线AP的合理选型和部署非常重要。今天给大家安排。这篇文章,给你总结了6类典型的无线组网场所,针对每种场景的特点,给出相应的设备选型和部署的方案,同时整理了一些部署无线AP过程中容易忽略的细节,希望能给你日后组网提供一些帮助。01不同类型的AP,不同的使用环境不......
  • ArrayList的扩容机制详解,解决面试难题!
    前言大家好,我是chowley,不知各位在面试中,是否被问过‘读没读过相关框架的源码?’这个经典问题?我最近就遇到了,虽然我之前读过,但这玩意干读不进味啊今天我就来讲讲ArrayList,这个白家长谈的经典数据结构的扩容机制!ArrayList在Java的集合框架中,ArrayList是一个非常常用的动态数组实......
  • 多快好省| 4 条策略完美化解 BI 场景的敏感数据保护难题
    超过2000人每天取数、用数查看报表BI平台原生的权限控制和脱敏难以有效落地敏感数据基本处于“裸奔”状态4条策略如何实现有效保护?项目背景金融消费者个人信息保护与数据安全风险排查成为近年来金融监管机构的检查重点之一。G保险企业开展数据安全治理自查,已逐步完成了数据分类分......
  • 孩子遇到的难题,父母正确的第一反应很重要!
         共情型、乐观型、战略型 ......
  • 如何缓解现代企业亟需应对的数据安全难题?
    在......