首页 > 其他分享 >P8844 [传智杯 #4 初赛] 小卡与落叶

P8844 [传智杯 #4 初赛] 小卡与落叶

时间:2022-11-14 14:01:48浏览次数:49  
标签:传智杯 fa int head 初赛 dep 小卡 节点 ec

简要题意

给出一个 \(n\) 个节点的以 \(1\) 为根的树,每一个节点 \(i\) 带权 \(w_i\),初始时所有节点的权均为 \(0\)。有 \(m\) 个操作,支持以下操作:

  • 1 x,对于所有树上节点 \(i\),进行以下操作:

\[w_i=\begin{cases}1&(\operatorname{Depth}({i})\geq x)\\0&(\text{otherwise})\end{cases} \]

  • 2 x,询问以 \(x\) 为根的子树的所有节点的权值和。

\(1 \leq n,m \leq 10^{5}\),允许离线

思路

首先可以得出 2 操作的答案仅与之前的最后一次 1 操作有关,所以我们把操作离线下来,设最后一次 \(1\) 操作是 1 t,那么操作 2 v 其实是在求以 \(t\) 为根的子树中有多少个深度大于等于 \(t\) 的节点。统计深度自然想到按照深度建一个权值线段树森林。树上 DFS 处理询问。先把儿子合并到父亲上,然后直接回答查询即可(这里询问是线段树基本操作,不讲)。

时间复杂度 \(O(m\log n)\)。

代码

#include <bits/stdc++.h>
#define int long long
#define ls(i) (t[i].ls)
#define rs(i) (t[i].rs)
#define mid ((l+r)>>1)
using namespace std;

const int N = 1e5+5;
struct node{
	int ls,rs,v;
} t[N<<8];
int root[100005],tot;
int n,m;

inline void newnode(int &i){
	if(!i)i=(++tot);
}

void pushup(int i){
	t[i].v=t[ls(i)].v+t[rs(i)].v;
}

void insert(int p,int v,int &i,int l,int r){
	newnode(i);
	if(l==r){
		t[i].v++;
		return;
	}
	if(p<=mid){
		insert(p,v,ls(i),l,mid);
	}
	else{
		insert(p,v,rs(i),mid+1,r);
	}
	pushup(i);
}

void merge(int &x,int &y){
	if(x==0||y==0){
		if(y)x=y;
		if(x)y=x;
		return;
	}
	t[x].v+=t[y].v;
	merge(ls(x),ls(y));
	merge(rs(x),rs(y));
}

int query(int ql,int qr,int i,int l,int r){
	if(!i)return 0;
	if(ql<=l&&r<=qr){
		return t[i].v;
	}
	int res=0;
	if(ql<=mid){
		res+=query(ql,qr,ls(i),l,mid);
	}
	if(qr>mid){
		res+=query(ql,qr,rs(i),mid+1,r);
	}
	return res;
}

struct edge{
	int nxt,to;
} g[1000005];
int head[1000005],ec;
void add(int u,int v){
	g[++ec].nxt=head[u];
	g[ec].to=v;
	head[u]=ec;
}

int dep[1000005];
struct Query{
	int x,tmd;
	Query(int X=0,int TMD=0){
		x=X,tmd=TMD;
	}
};

int ret[1000005];
vector<Query> q[100005];

void dfs(int u,int fa){
	dep[u]=dep[fa]+1;
	for(int i=head[u];i;i=g[i].nxt){
		int v=g[i].to;
		if(v==fa)continue;
		dfs(v,u);
	}
}

void solve(int u,int fa){
	for(int i=head[u];i;i=g[i].nxt){
		int v=g[i].to;
		if(v==fa)continue;
		solve(v,u);
		merge(root[u],root[v]);
	}
	for(Query i:q[u]){
		ret[i.tmd]=query(i.x,n,root[u],1,n);
	}
}

signed main(){
	ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
	cin>>n>>m;
	for(int i=1,u,v;i<n;i++){
		cin>>u>>v;
		add(u,v);add(v,u);
	}
	dfs(1,0);
	for(int i=1;i<=n;i++){
		insert(dep[i],1,root[i],1,n);
	}
	int last_dep=n+1,two_cnt=0;
	while(m--){
		int op,u;
		cin>>op>>u;
		if(op==1){
			last_dep=u;
			continue;
		}
		q[u].push_back(Query(last_dep,(++two_cnt)));
	}
	solve(1,0);
	for(int i=1;i<=two_cnt;i++){
		cout<<ret[i]<<'\n';
	}
	return 0;
}

标签:传智杯,fa,int,head,初赛,dep,小卡,节点,ec
From: https://www.cnblogs.com/zheyuanxie/p/p8844.html

相关文章

  • P7137 [THUPC2021 初赛] 切切糕(博弈 概率)
    P7137[THUPC2021初赛]切切糕->双倍经验:GameonSum(HardVersion)有\(n\)块方蛋糕,绝顶聪明的Sight和Sirrel决定将每块蛋糕都分成两块各自品尝。Sight会依次......
  • 题解 P8827 [传智杯 #3 初赛] 森林
    本题解提供两种做法。做法一为了叙述方便,先引入\(n\)级母树的概念。定义\(1\)级母树即为该子树被删去前,其所在的原来的完整的树。如下图,以\(5\)为根的一级母树......
  • 百度之星 初赛 A 杭电6376 度度熊剪纸条
    C度度熊剪纸条链接:​​​点我​​​ProblemDescription度度熊有一张纸条和一把剪刀。纸条上依次写着N个数字,数字只可能是0或者1。度度熊想在纸条上剪K刀(每一刀......
  • 初赛自测
    postedon2021-09-2000:05:18|under灌水|source如果你记了答案可以测一下(误)S#include<cctype>#include<string>#include<cstring>#include<iostream>#in......
  • LOJ #6175. 「美团 CodeM 初赛 Round B」黑白树
    题目链接:​​传送门​​一个很贪心的数位dp显然从叶节点开始染色是优的因为相比更靠上的节点来说会染到更多的节点那就先去染叶节点,在他的父亲节点处判断是否被覆盖如果......
  • 10.7校赛初赛
    整体难度不大,但是因为前期冲的太猛了,15分钟做了3道题,后期跟风做题,看着别人都6题甚至AK了,就有点慌张,后期基本上没有深入思考,状态很浮躁,导致最终结果很差。因为后一个小时都......
  • 初赛复习
    初赛复习计算机计算机的分类按年代分类\(1946\text{至}1958\quad\text{电子管}\)\(1959\text{至}1964\quad\text{晶体管}\)\(1965\text{至......
  • 2022第五空间网络安全初赛-md
    title:2022第五空间网络安全初赛.mddate:2022-09-2011:06:40tags:2022第五空间网络安全初赛5_web_BaliYun简单的文件上传刚开始别人出的很快就以为是不同的文件......
  • CSP-j/s 2022 第一轮(初赛)游记
    CSP-J/S2022第一轮游记HA(河南)省今年cspj报名人数较去年增长66%……挺离谱的eee由于没有疫情,初赛定在了线下举办,似乎今年pj要卡掉\(1e3\)个人左右CwC一些文中的名词......
  • 2022CSP-S初赛游记
    锅奇多的一次Day0会不会因为初赛就AFO力(大悲躺在床上,头脑发慌,难以入睡Day111:14昏从uoj群里拿到了J组试卷wocT3考指针,S组考这个......