首页 > 编程语言 >第二十届浙大城市学院程序设计竞赛 I.Magic Tree DFS序线段树

第二十届浙大城市学院程序设计竞赛 I.Magic Tree DFS序线段树

时间:2023-04-05 18:59:34浏览次数:54  
标签:std Magic int ll Tree DFS long include define

传送门

大致思路:

  我们知道dfs序上的整颗子树dfs序编号连续,因为每次删除一个点或者新增一个点都导致子树上所有点的深度加一或者减一。由于是区间修改所以我们考虑dfs序上建线段树。

  

#include <iostream>
#include <cstring>
#include <iomanip>
#include <algorithm>
#include <stack>
#include <queue>
#include <numeric>
#include <cassert>
#include <bitset>
#include <cstdio>
#include <vector>
#include <unordered_set>
#include <cmath>
#include <map>
#include <unordered_map>
#include <set>
#include <deque>
#include <tuple>
#include <array>
 
#define all(a) a.begin(), a.end()
#define cnt0(x) __builtin_ctz(x)
#define endl '\n'
#define ll long long
#define ull unsigned long long
#define cntone(x) __builtin_popcount(x)
#define db double
#define fs first
#define se second
#define AC main(void)
#define ls u << 1
#define rs u << 1 | 1
typedef std::pair<int, int> PII;
#define HYS std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);
const long double eps = 1e-9;
int MOD = 571373;

const int N = 4e5 + 10, M = 6e5 + 10;
const int INF = 0x3f3f3f3f;

ll min(ll a, ll b)	{return a > b ? b : a;}
ll max(ll a, ll b)	{return a > b ? a : b;}
int min(int a, int b)	{return a > b ? b : a;}
int max(int a, int b)	{return a > b ? a : b;}


int n , m, _;

int d1[] = {0, 0, 1, -1};
int d2[] = {1, -1, 0, 0};

int w[N], h[N], e[N << 1], ne[N << 1], idx;
int id[N], nw[N], cnt;
int dep[N], sz[N], top[N], fa[N], son[N], ans[N], rid[N];
int vis[N];
int realfa[N];
int realson[N];
int iddeep[N];

struct node{
	int l, r;
	int add;
	int v;
}tr[N << 2];

inline void build(int u, int l, int r){
	tr[u] = {l, r};
	if(l == r){
		tr[u].v = iddeep[l];
		return ;
	}
	
	int mid = l + r >> 1;
	
	build(u << 1, l, mid);
	build(u << 1 | 1, mid + 1, r);
}

inline void pushdown(int u){
	if(tr[u].add){
		int x = tr[u].add;
		tr[ls].v += x;
		tr[rs].v += x;
		tr[ls].add += x;
		tr[rs].add += x;
		tr[u].add = 0;
	}
}

inline int query(int u, int x){
	if(tr[u].l == tr[u].r)	return tr[u].v;
	
	pushdown(u);
	
	int mid = tr[u].l + tr[u].r >> 1;
	if(x <= mid)	return query(u << 1, x);
	return query(u << 1 | 1, x);
}

inline void modify(int u, int l, int r, int x){
	if(tr[u].l == tr[u].r){
		tr[u].v += x;
		return ;
	}
	
	if(tr[u].l >= l && tr[u].r <= r){
		tr[u].add += x;
		return ;
	}
	
	pushdown(u);
	
	int mid = tr[u].l + tr[u].r >> 1;
	
	if(l <= mid)	modify(u << 1, l, r, x);
	if(r > mid)	modify(u << 1 | 1, l, r, x);
}

inline void ADD(int u, int x, int v){
	if(tr[u].l == tr[u].r){
		tr[u].v = v;
		return ;
	}
	
	pushdown(u);
	
	int mid = tr[u].l + tr[u].r >> 1;
	if(x <= mid)	ADD(u << 1, x, v);
	else ADD(u << 1 | 1, x, v);
}

inline void add(int a, int b){
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
//统计子树大小 并且 找出重儿子
inline void dfs1(int u, int father, int depth){
    dep[u] = depth, fa[u] = father, sz[u] = 1;
    for (int i = h[u]; ~i; i = ne[i]){
        int j = e[i];
        if (j == father || realfa[j] != u) continue;
        if(j <= n)
        	dfs1(j, u, depth + 1);
        else dfs1(j, u, depth);
        sz[u] += sz[j];
        if (sz[son[u]] < sz[j]) son[u] = j;
    }
}

//dfs序 nw标记dfs为cnt的时候对应的树上点的权值 top标记父亲是谁
inline void dfs2(int u, int t){
    id[u] = ++ cnt, nw[cnt] = w[u], top[u] = t, rid[cnt] = u;
    iddeep[id[u]] = dep[u];
    if(!son[u]) return;
    dfs2(son[u], t);
    for (int i = h[u]; ~i; i = ne[i]){
        int j = e[i];
        if (j == fa[u] || j == son[u] || realfa[j] != u) continue;
        dfs2(j, j);
    }
}

inline void Init(){
	dfs1(1, -1, 1);
        dfs2(1, 1);
}

inline void solve(){
    std::cin >> n >> m;
    
    memset(h, -1, sizeof h);
    
    std::vector<int> last(n + 1);
    for(int i = 2; i <= n; i ++){
    	int x;
    	std::cin >> x;
    	realfa[i] = x;
    	add(x, i);
    	last[i] = x;
    }
    
    std::vector<PII> g(m);
    for(int i = 0; i < m; i ++){
    	int op, x;
    	std::cin >> op >> x;
    	g[i] = {op, x};
    	if(op == 1){
    		int father = realfa[x];
    		realfa[x] = i + n + 1;
    		realfa[i + n + 1] = father;
    		add(i + n + 1, x);
    		add(father, i + n + 1);
    	}
    }
    
    Init();
    
    int szz = n + m;

	build(1, 1, szz);

	for(int i = 2; i <= szz; i ++){
		if(i <= n){
			realfa[i] = last[i];
			realson[last[i]] = i;
		}else realfa[i] = realson[i] = 0;
	}

	for(int i = 0; i < m; i ++){
		auto &[op, x] = g[i];
		if(op == 1){
			int father = realfa[x];
			modify(1, id[x], id[x] + sz[x] - 1, 1);
			realfa[i + n + 1] = father;
			realfa[x] = i + n + 1;
			realson[father] = n + i + 1;
			realson[n + i + 1] = x;
			int depth = query(1, id[father]);
			ADD(1, id[i + n + 1], depth + 1);
		}else if(op == 2){
			int father = realfa[x];
			int sonn = realson[x];
			realfa[sonn] = father;
			realson[father] = sonn;
			modify(1, id[x], id[x] + sz[x] - 1, -1);
		}else{
			std::cout << query(1, id[x]) << '\n';
		}
	}
}


int main(){
    HYS
	_ = 1;
  	//_ = read();
	while(_ --)
    	solve();

    return 0;
}

标签:std,Magic,int,ll,Tree,DFS,long,include,define
From: https://www.cnblogs.com/qdhys/p/17290371.html

相关文章

  • [LeetCode] 1339. Maximum Product of Splitted Binary Tree 分裂二叉树的最大乘积
    Giventhe root ofabinarytree,splitthebinarytreeintotwosubtreesbyremovingoneedgesuchthattheproductofthesumsofthesubtreesismaximized.Return themaximumproductofthesumsofthetwosubtrees.Sincetheanswermaybetoolarge,re......
  • 蓝桥杯(全球变暖dfs)
    蓝桥杯(全球变暖dfs)importjava.util.Scanner;/***该题使用了深度优先算法dfs用于把相连的#号当成一块大陆,并通过数组记录下有几块大陆*dfs算法并不难,只要对用dfs处理过后留下的aes数组和sea数组进行处理得到结果即可*我的思路就是*1、sea数组记录源数据,然后判断是......
  • hdfs集群的扩容和缩容
    目录1、背景2、集群黑白名单3、准备一台新的机器并配置好hadoop环境3.1我们现有的集群规划3.2准备一台新的机器3.2.1查看新机器的ip3.2.2修改主机名和host映射3.2.3配置时间同步3.2.4关闭防火墙3.2.5新建hadoop部署用户3.2.6复制hadoop04机器上的/etc/hosts文件到集群的另......
  • ztree如何引入
    例如,目录结构为:代码:<scripttype="text/javascript"src="/static/jquery/jquery-1.12.4.min.js"></script><linkrel="stylesheet"href="/static/zTree_v3/css/demo.css"type="text/css"><!--如果......
  • POJ 2773 Happy 2006 二分+容斥原理(二进制枚举或dfs)
    Happy2006TimeLimit: 3000MS MemoryLimit: 65536KTotalSubmissions: 14003 Accepted: 4946DescriptionTwopositiveintegersaresaidtoberelativelyprimetoeachotheriftheGreatCommonDivisor(GCD)is1.Forinstance,1,3,5,7,9...areallrelativel......
  • DecisionTreeClassifier&DecisionTreeClassRegression
    DecisionTreeClassifierfromsklearn.datasetsimportload_wine#红酒数据集fromsklearn.treeimportDecisionTreeClassifier,export_graphviz#决策树,画树fromsklearn.model_selectionimporttrain_test_split#数据集划分importgraphvizimportmatplotlib.pyplo......
  • 【FastDFS分布式文件系统】5.FastDFS客户端的配置、启动和常用命令
    上一篇我们介绍了FastDFS服务端的tracker追踪服务器和storage存储服务器,本篇来介绍一下客户端的启动,以及外部客户端如何与FastDFS服务端进行连接。和之前一样,服务端部署在三台服务器上:其中192.168.195.129是tracker追踪服务器,192.168.195.130和192.168.195.131......
  • 【FastDFS分布式文件系统】6.FastDFS客户端启动与Java连接
    上一篇我们讲解了如何配置和启动FastDFS客户端,以及客户端上传下载的一些常用命令。那么,在许多需要进行分布式文件上传与下载的系统中,就不能像执行Linux命令一样去上传和下载文件,它们需要使用开发系统的语言去操作客户端使用其命令与服务端进行交互,此时FastDFS......
  • New Year Tree
    NewYearTree线段树,打标记,位运算操作1,区间赋值,很容易的线段树操作对于询问以\(u\)为根的子树上的所有节点的颜色数量,一开始我在线段树里开了一个大小61的数组,喜提MLE,但后续观察发现,\(1<<60\leq\text{longlong}\),所以我们设每种颜色$c_i$的值为\(1<<c_i\),对于updat......
  • dfs理解
    dfs理解201深搜(DFS)哔哩哔哩bilibili董晓-博客园(cnblogs.com)深搜的时机在扩展当前节点的邻边之前,即for当前节点的儿子节点之前,刚进入当前这个节点。for完当前节点的所有儿子节点之后,要离开当前节点了。开始for当前节点的扩展邻边时,即刚从当前节点出去。此时可以从父节点向......