首页 > 其他分享 >[USACO17JAN] Promotion Counting P 题解

[USACO17JAN] Promotion Counting P 题解

时间:2023-10-11 22:14:04浏览次数:37  
标签:ch 题解 复杂度 USACO17JAN 子树 Promotion

[USACO17JAN] Promotion Counting P 题解

前言

好久没写题解了,今天趁我心情好赶紧水一篇。

思路

首先拿到这题,关键词检索:子树,比 \(p_i\) 大的,树状数组!现在考虑如何去掉其他子树的贡献……emm,我直接在算贡献的时候去掉其他子树的贡献不就好了!

当然,暴力去贡献复杂度肯定爆炸,这里考虑如何通过保留最多的信息来达到减少复杂度的目的。这里用了 DSU on Tree 的思想:保留重儿子的信息,而在递归完轻儿子后清空轻儿子的信息。每个点被再次遍历到,当且仅当它所在的子树大小翻倍。这样做复杂度是 \(O(n \log n)\) 的,套上树状数组的复杂度就是 \(O(n \log^2 n)\) 的。

代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+100;

int read() {
	int x = 0; char ch = getchar();
	while(ch<'0' || ch>'9') ch = getchar();
	while(ch>='0'&&ch<='9') x = x*10+(ch-48), ch = getchar();
	return x;
}
int n;
int lsh[N], a[N];
//dsu on tree?
int head[N], tot;
struct node {
	int nxt, to;
} edge[N<<1];
void add(int u, int v) {
	edge[++tot].nxt = head[u];
	edge[tot].to = v;
	head[u] = tot;
}

struct BIT {
	int tc[N];
	int lowbit(int x) {
		return x & (-x);
	}
	void insert(int pos, int val) {
//		printf("%d %d\n", pos, val);
		for(int i = pos; i<=n; i+=lowbit(i)) {
			tc[i]+=val;
		}
	}
	int query(int pos) {
		int ret = 0;
		for(int i = pos; i; i-=lowbit(i)) {
			ret+=tc[i];
		}
		return ret;
	}
}bt;
int siz[N], son[N];
void predfs(int u, int fath) {
	siz[u] = 1;
	for(int i = head[u]; i; i = edge[i].nxt) {
		int v = edge[i].to;
		if(v == fath) continue;
		predfs(v, u);
		siz[u]+=siz[v];
		if(siz[son[u]] < siz[v]) son[u] = v;
	}
}

int ans[N];
void pls(int u, int fath) {
	bt.insert(a[u], 1);
	for(int i = head[u]; i; i = edge[i].nxt) {
		int v = edge[i].to;
		if(v == fath) continue;
		pls(v, u);
	}
}
void del(int u, int fath) {
	bt.insert(a[u], -1);
	for(int i = head[u]; i; i = edge[i].nxt) {
		int v = edge[i].to;
		if(v == fath) continue;
		del(v, u);
	}
}
void dfs(int u, int fath, bool op) {
	for(int i = head[u], v; i; i = edge[i].nxt) {
		v = edge[i].to;
		if(v == fath || v == son[u]) continue;
		dfs(v, u, 1);
	}
	
	if(son[u]) dfs(son[u], u, 0);
	
	for(int i = head[u], v; i; i = edge[i].nxt) {
		v = edge[i].to;
		if(v == fath || v == son[u]) continue;
		pls(v, u); 
	}
	ans[u] = bt.query(n) - bt.query(a[u]);
	bt.insert(a[u], 1);
//	cout << u << " " << bt.query(n) << " " << bt.query(a[u]) << endl;
	if(op) del(u, fath);
}
int main() {
	n = read();
	for(int i = 1; i<=n; ++i) {
		a[i] = lsh[i] = read();
	}
	sort(lsh+1, lsh+n+1);
	for(int i = 1; i<=n; ++i) {
		a[i] = lower_bound(lsh+1, lsh+n+1, a[i])-lsh;
	}
	for(int i = 2; i<=n; ++i) {
		int u = read();
		add(u, i);
		add(i, u);
	}
	predfs(1, 0);
	dfs(1, 0, 0);
	for(int i = 1; i<=n; ++i) {
		printf("%d\n", ans[i]);
	}
	return 0;
}

后记:

后来翻题解发现自己完全是搞麻烦了。其实这个题在递归前后做个差就好……麻了。

完全不会捏

标签:ch,题解,复杂度,USACO17JAN,子树,Promotion
From: https://www.cnblogs.com/frostwood/p/17758325.html

相关文章

  • [USACO08FEB]meteor Shower S题解(bfs)
    题目描述贝茜听说一场特别的流星雨即将到来:这些流星会撞向地球,并摧毁它们所撞击的任何东西。她为自己的安全感到焦虑,发誓要找到一个安全的地方(一个永远不会被流星摧毁的地方)。如果将牧场放入一个直角坐标系中,贝茜现在的位置是原点,并且,贝茜不能踏上一块被流星砸过的土地。根据预......
  • FileZilla 超时连接失败问题解决办法
    1.确保ubuntu支持FTP   就是安装ssh。      首先查看你有没有:sudops-e|grepssh红色箭头存在就代表你有的!如果没有那就去安装吧!2.确保ubuntu和windouws都关闭防火墙!【1】ubuntu打开终端输入:sudoufwdisable就会出现【2】windows中在搜索框中搜索防火墙:关闭......
  • 网络规划设计师真题解析--SNMP管理(安全威胁)
    在网络管理中要防范各种安全威胁。在SNMP管理中,无法防范的安全威胁是(35)。A.篡改管理信息:通过改变传输中的SNMP报文实施未经授权的管理操作B.通信分析:第三者分析管理实体之间的通信规律,从而获取管理信息C.假冒合法用户:未经授权的用户冒充授权用户,企图实施管理操作D.截获:未经授权......
  • P1457 [USACO2.1] 城堡 The Castle 题解
    分析感觉没有蓝题难度一道bfs题目,相较于大部分bfs题,它较为复杂,但分析一下还是很好水过的。建立墙时,可以用三维数组,\(wall_{~i,~j,~pos}\)表示第\(i\)行第\(j\)列\(pos\)方向有墙。观察发现,\(8=2^3,4=2^2,2=2^1,1=2^1\),于是可以用位运算快速储存。这里给出......
  • Ubuntu无法联网问题解决
    前言会有不同种原因导致系统无法联网,我遇到的可能只是其中一种,建议多问问ChatGPT,每一步遇到的问题问问人家应该能解决我遇到的情况是,之前一直能联网,然后一段时间不登就连不上网,然后又好了,然后又连不上网因此也把我这种情况的解决方案记录一下,以备不时之需   解决步骤......
  • Shuffle 题解
    Shuffle题目大意给定一个长度为\(n\)的01序列\(a\),你可以进行至多一次以下操作:选定\(a\)的一个连续段,满足连续段内恰好有\(k\)个\(1\),将该连续段任意排列。问能产生多少种不同的01序列。思路分析(这题\(n\)完全可以开到\(10^6\)或是\(10^7\),因为存在\(O(......
  • Hadoop问题解决(5)
    当一个HDFS系统同时处理许多个并行的put操作,往HDFS上传数据时,有时候会出现dfsclient端发生socket链接超时的报错,有的时候甚至会由于这种原因导致最终的put操作失败,造成数据上传不完整。log类似如下:Alldatanodes ***arebad.Aborting...类似这样的错误,常常会在并行的put操作......
  • Debian12安装MySQL8实践及问题解决方案
    Debian12安装MySQL数据库,常规操作:sudoaptsearchmysql&sudoaptinstallmysql,肯定是行不通的,因为没有安装包。把我的安装过程以及遇到问题的解决方案记录下来,供大家借鉴。第一步更新系统、下载软件包命令如下:sudoaptupdatewgethttps://dev.mysql.com/get/mysql-apt-co......
  • 【题解 P3586】 LOG
    [POI2015]LOG题目描述维护一个长度为\(n\)的序列,一开始都是\(0\),支持以下两种操作:Uka将序列中第\(k\)个数修改为\(a\)。Zcs在这个序列上,每次选出\(c\)个正数,并将它们都减去\(1\),询问能否进行\(s\)次操作。每次询问独立,即每次询问不会对序列进行修改。输......
  • 题解 AcWing 359.创世纪
    题目描述给你一个\(n\)个点\(n\)条边的有向图,若选了当前节点,那么当前节点的儿子节点至少有一个不能选。求最多能选多少个点。具体思路显然是一棵基环树,因此考虑基环树dp。我们先不管环的条件,先考虑朴素的树形dp。设\(f_{x,0}\)表示\(x\)节点不选,最多可以选多少个......