• poj3321


    树状数组

    题意:给定一棵树,某些节点上有苹果,多次询问各子树上的节点数,并且在询问的中途随时可能新增和删除苹果。

    分析:dfs遍历树的同时,对每个点标注时间,每个点有一个开始时间和一个结束时间,把这两个时间当做下标,该点的苹果个数(1或0)填入数组的两个对应位。子树中结点的时间段一定是根节点时间段的子段,所以求子树苹果数,只需求数组某区间的和即可。用树状数组比较快。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    using namespace std;
    
    #define maxn  200005
    
    struct sedge
    {
    	int v, next;
    }edge[maxn];
    
    struct sfork
    {
    	int s, e;
    }fork[maxn];
    
    int edgenum, head[maxn], xtime, ar[maxn * 2], apple[maxn], N;
    
    void addedge(int a, int b)
    {
    	edge[edgenum].v = b;
    	edge[edgenum].next = head[a];
    	head[a] = edgenum;
    	edgenum++;
    }
    
    void dfs(int a)
    {
    	fork[a].s = xtime;
    	xtime++;
    	for (int i = head[a]; i != -1; i = edge[i].next)
    			dfs(edge[i].v);
    	fork[a].e = xtime;
    	xtime++;
    }
    
    int lowbit(int t)
    {
    	return t &(-t);
    }
    
    void add(int i, int v)
    {
    	for (; i < N; ar[i] += v, i += lowbit(i));
    }
    
    int sum(int i)
    {
    	int s = 0;
    	for (; i > 0; s += ar[i], i-=lowbit(i));
    	return s;
    }
    int main()
    {
    	//freopen("D:\\t.txt", "r", stdin);
    	edgenum = 0;
    	xtime = 1;
    	memset(head, -1, sizeof(head));
    	int n;
    	scanf("%d", &n);
    	for (int i = 0; i < n - 1; i++)
    	{
    		int a, b;
    		scanf("%d%d", &a, &b);
    		addedge(a, b);
    	}
    	dfs(1);
    	memset(ar, 0, sizeof(ar));
    	N = n * 2;
    	for (int i = 1; i <= N; i++)
    		ar[i] = (i) - (i - lowbit(i));
    	for (int i = 1; i <= n; i++)
    		apple[i] = 1;
    	int q;
    	scanf("%d", &q);
    	getchar();
    	for (int i = 0; i < q; i++)
    	{
    		char ch;
    		int num;
    		scanf("%c%d", &ch, &num);
    		getchar();
    		if (ch == 'C')
    		{
    			int temp;
    			if (apple[num] == 1)
    				temp = -1;
    			else
    				temp = 1;
    			add(fork[num].s, temp);
    			add(fork[num].e, temp);
    			apple[num] += temp;
    		}
    		else
    			printf("%d\n", (sum(fork[num].e) - sum(fork[num].s))/2 + apple[num]);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    二、线程的生命周期
    一、多线程基础
    Java中的三种代理模式(转载)
    SpringBoot+Thymeleaf实现国际化
    Centos7设置Jar包开机自启动
    Centos7安装及卸载RabbitMQ
    Nacos无法读取配置中心数据
    解决SSH连接Linux系统特别慢的问题
    KMP字符串匹配算法
    格雷厄姆扫描法解凸壳问题
  • 原文地址:https://www.cnblogs.com/rainydays/p/1948628.html
Copyright © 2020-2023  润新知