列表

详情


NC244121. 剖分

描述

牛牛有一颗包含 n 个结点的二叉树,这些结点编号为 。这颗树被定义为:
    1、以结点 1 为根。
    2、编号为 x 结点的两个儿子编号分别为:
    3、每个结点的权重初始都为 0。

牛牛接下来会对这颗树进行 m 次操作,操作的格式是以下四种之一:
    1、 (这里 )代表牛牛将以编号 x 为根结点的子树中所有结点的权重 +1。
    2、 (这里 )代表牛牛将以编号 x 为根结点的子树外的所有结点权重 +1。
    3、 (这里 )代表牛牛将根结点到编号 x 结点的路径上的所有结点权重 +1。
    4、 (这里 )代表牛牛将根节点到编号 x 结点的路径上的结点之外的所有结点权重 +1。

牛妹想知道当牛牛的所有操作结束之后,树中权重为 的结点的数量分别是多少。

输入描述

第一行输入两个空格分隔的整数:
接下来 m 行,每行描述了一个牛牛进行的操作。
保证:




输出描述

输出一行共  个整数,代表答案。

示例1

输入:

7 4
1 2
3 5
4 3
2 7

输出:

0 2 2 1 2

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 592ms, 内存消耗: 158076K, 提交时间: 2022-11-25 21:13:50

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e7+10;
int w[N],a[N],b[N],n;
void dfs1(int u,int t){
    if(u<1)return;
    if(t)a[u]++;
    else a[u]--;
    dfs1(u/2,t);
}
signed main()
{
	int m,op,x,ans=0;
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        cin>>op>>x;
        if(op==1)b[x]++;
        else if(op==2)b[x]--,ans++;
        else if(op==3)dfs1(x,1);
        else dfs1(x,0),ans++;
    }
    for(int i=1;i<=n;i++){
        b[i]+=b[i/2];
    }
    for(int i=1;i<=n;i++){
        w[a[i]+ans+b[i]]++;
    }
    for(int i=0;i<=m;i++)
        cout<<w[i]<<" ";
    return 0;
}

C++(clang++ 11.0.1) 解法, 执行用时: 1160ms, 内存消耗: 104520K, 提交时间: 2022-11-27 17:07:56

#include<bits/stdc++.h>
using namespace std;
const int N=1e7+10;
typedef long long LL;
int d[N],f[N],v[N];
int n,m;
void dfs(int u,int fa)
{
	if(u>n)return ;
	d[u]+=d[fa];
	dfs(2*u,u);
	dfs(2*u+1,u);
	f[u]=f[u]+f[2*u]+f[2*u+1];
}
int main()
{
	
	cin>>n>>m;
	int g=0;
	for(int i=0;i<m;i++)
	{
		int op,x;
		cin>>op>>x;
		if(op==1)d[x]++;
		else if(op==2)d[x]--,g++;
		else if(op==3)f[x]++;
		else f[x]--,g++;
	}
	dfs(1,0);
	map<int,int>v;
	for(int i=1;i<=n;i++)v[g+d[i]+f[i]]++;
	for(int i=0;i<=m;i++)cout<<v[i]<<' ';
	
}

上一题