[Codevs] 1228 苹果树

1228 苹果树

时间限制: 1 s

空间限制: 128000 KB

题目等级 : 钻石 Diamond

题目描述 Description

在卡卡的房子外面,有一棵苹果树。每年的春天,树上总会结出很多的苹果。卡卡非常喜欢吃苹果,所以他一直都精心的呵护这棵苹果树。我们知道树是有很多分叉点的,苹果会长在枝条的分叉点上面,且不会有两个苹果结在一起。卡卡很想知道一个分叉点所代表的子树上所结的苹果的数目,以便研究苹果树哪些枝条的结果能力比较强。

卡卡所知道的是,每隔一些时间,某些分叉点上会结出一些苹果,但是卡卡所不知道的是,总会有一些调皮的小孩来树上摘走一些苹果。

于是我们定义两种操作:


C x


表示编号为x的分叉点的状态被改变(原来有苹果的话,就被摘掉,原来没有的话,就结出一个苹果)


G x


查询编号为x的分叉点所代表的子树中有多少个苹果

我们假定一开始的时候,树上全都是苹果,也包括作为根结点的分叉1。

输入描述 Input Description

第一行一个数N (n<=100000)

接下来n-1行,每行2个数u,v,表示分叉点u和分叉点v是直接相连的。

再接下来一行一个数M,(M<=100000)表示询问数

接下来M行,表示询问,询问的格式如题目所述Q x或者C x

输出描述 Output Description

对于每个Q x的询问,请输出相应的结果,每行输出一个

样例输入 Sample Input

3

1 2

1 3

3

Q 1

C 2

Q 1

样例输出 Sample Output

3

2

分析 Analysis

首先这道题理论基础:DFS序(树操)+ 线段树

好在那个长苹果不是每秒,不然我就ctrl+w了qwq

首先读进来后撸成DFS序为基础的线性结构

那么根据DFS序,这道题可以化归为:树上单点修改 + 求子树和

如果到这里还没看懂请补全DFS序的理论部分qwq(然后怎么做超显然的)

-------------------------------------------------------------------------

我第一次拿到这道题的时候,还真不知道怎么写

好在CZL夏令营的时候帮我补了树操

orzCZL

代码 Code

  1 #include<cstdio>
  2 #include<iostream>
  3 #define mid (L+R)/2
  4 #define lc (rt<<1)
  5 #define rc (rt<<1|1)
  6 #define maxn 1000000
  7 using namespace std;
  8
  9 int dfn[maxn],TIM = 1,dfn_t[maxn],n,a,b,c,m,pos,tl[maxn];
 10 char ctr;
 11
 12 struct edge{
 13     int from,v;
 14 }e[maxn];
 15
 16 struct node{
 17     int sum;
 18 }Tree[maxn];
 19
 20 void maintain(int rt){
 21     Tree[rt].sum = Tree[lc].sum+Tree[rc].sum;
 22 }
 23
 24 void build(int rt,int L,int R){
 25     if(L == R) Tree[rt].sum = 1;
 26     else{
 27         build(lc,L,mid);
 28         build(rc,mid+1,R);
 29
 30         maintain(rt);
 31     }
 32 }
 33
 34 void add(int rt,int L,int R,int pos){
 35     if(L == R) Tree[rt].sum ^= 1;
 36     else{
 37         if(pos <= mid) add(lc,L,mid,pos);
 38         else add(rc,mid+1,R,pos);
 39
 40         maintain(rt);
 41     }
 42 }
 43
 44 int query(int rt,int L,int R,int qL,int qR){
 45     if(qL <= L && R <= qR) return Tree[rt].sum;
 46     else{
 47         int ans = 0;
 48         if(qL <= mid) ans += query(lc,L,mid,qL,qR);
 49         if(qR > mid) ans += query(rc,mid+1,R,qL,qR);
 50         return ans;
 51     }
 52 }
 53
 54 void PRINT(int rt,int L,int R){
 55     if(L == R) printf("%d ",Tree[rt].sum);
 56     else{
 57         PRINT(lc,L,mid);
 58         PRINT(rc,mid+1,R);
 59     }
 60 }
 61
 62 int tot,first[maxn];
 63 void insert(int u,int v){
 64     tot++;
 65     e[tot].from = first[u];
 66     e[tot].v = v;
 67     first[u] = tot;
 68 }
 69
 70 void dfs(int now,int pre){
 71     dfn[now] = TIM++;
 72     tl[dfn[now]] = now;
 73 //    Tree[dfn[now]].sum = 1;
 74     for(int i = first[now];i;i = e[i].from){
 75         int v = e[i].v;
 76         if(v != pre){
 77             dfs(v,now);
 78         }
 79     }dfn_t[now] = TIM++;
 80     tl[dfn_t[now]] = now;
 81 }
 82
 83 int main(){
 84     scanf("%d",&n);
 85     for(int i = 1;i < n;i++){
 86         scanf("%d%d",&a,&b);
 87         insert(a,b);
 88         insert(b,a);
 89     }
 90
 91
 92     dfs(1,-1);
 93     TIM--;
 94 //    build(1,1,TIM-1);
 95     for(int i = 1;i <= n;i++){
 96         add(1,1,TIM,dfn[i]);
 97     }
 98
 99     scanf("%d",&m);
100     for(int i = 1;i <= m;i++){
101         cin >> ctr >> pos;
102         if(ctr == ‘C‘) add(1,1,TIM,dfn[pos]);
103         else printf("%d\n",query(1,1,TIM,dfn[pos],dfn_t[pos]));
104 //        PRINT(1,1,TIM-1);cout << endl;
105     }
106
107 //    for(int i = 1;i <= n;i++){
108 //        printf("%d ",dfn[i]);
109 //    }cout << "##";
110
111 //    for(int i = 1;i <= TIM;i++) printf("%d ",tl[i]);
112
113     return 0;
114 }

情绪低落= =

时间: 2024-12-19 19:35:57

[Codevs] 1228 苹果树的相关文章

codevs 1228 苹果树 树链剖分讲解

题目:codevs 1228 苹果树 链接:http://codevs.cn/problem/1228/ 看了这么多树链剖分的解释,几个小时后总算把树链剖分弄懂了. 树链剖分的功能:快速修改,查询树上的路径. 比如一颗树 首先,我们要把树剖分成树链.定义: fa[x]是x节点的上一层节点(就是他的爸爸). deep[x]是x节点的深度. num[x]是x节点下面的子节点的数量(包括自己) son[x]重儿子:一个节点的儿子的num[x]值最大的节点.其他的儿子都是轻儿子. 重链:重儿子连接在一起

codevs——1228 苹果树

1228 苹果树 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description 在卡卡的房子外面,有一棵苹果树.每年的春天,树上总会结出很多的苹果.卡卡非常喜欢吃苹果,所以他一直都精心的呵护这棵苹果树.我们知道树是有很多分叉点的,苹果会长在枝条的分叉点上面,且不会有两个苹果结在一起.卡卡很想知道一个分叉点所代表的子树上所结的苹果的数目,以便研究苹果树哪些枝条的结果能力比较强. 卡卡所知道的是,每隔一些时间,某些分叉点

AC日记——苹果树 codevs 1228

1228 苹果树 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description 在卡卡的房子外面,有一棵苹果树.每年的春天,树上总会结出很多的苹果.卡卡非常喜欢吃苹果,所以他一直都精心的呵护这棵苹果树.我们知道树是有很多分叉点的,苹果会长在枝条的分叉点上面,且不会有两个苹果结在一起.卡卡很想知道一个分叉点所代表的子树上所结的苹果的数目,以便研究苹果树哪些枝条的结果能力比较强. 卡卡所知道的是,每隔一些时间,某些分叉点

苹果树(线段树+Dfs序)

1228 苹果树 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 在卡卡的房子外面,有一棵苹果树.每年的春天,树上总会结出很多的苹果.卡卡非常喜欢吃苹果,所以他一直都精心的呵护这棵苹果树.我们知道树是有很多分叉点的,苹果会长在枝条的分叉点上面,且不会有两个苹果结在一起.卡卡很想知道一个分叉点所代表的子树上所结的苹果的数目,以便研究苹果树哪些枝条的结果能力比较强. 卡卡所知道的是,每隔一些时间,某些分叉点上会结出一些苹果,但

线段树1

线段树的基本操作 1.特点:与普通的树不同,线段树存取的是某一个区间,它在各个节点保存一条线段. 2.节点储存方式:(结构体) 方式一:数组储存 struct Tree { int leftnode, rightnode; //区间的最左端和最右端 long long sum; //该节点储存区间的值 } tree[N *4]; //比常规储存的数组要大四倍(Be careful!) 方式二:链表储存(自己了解) struct Tree { int Left, Right; Tree *Left

二叉苹果树(codevs 5565)树形DP

题目描述 Description 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点)这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1.我们用一根树枝两端连接的结点的编号来描述一根树枝的位置.现在这颗树枝条太多了,需要剪枝.但是一些树枝上长有苹果.       给定需要保留的树枝数量,求出最多能留住多少苹果. 输入描述 Input Description 第1行2个数,N和Q(1<=Q<= N,1<N<=100).N表示树的结点数,Q

[ CodeVS冲杯之路 ] P2492

不充钱,你怎么AC? 题目:http://codevs.cn/problem/2492/ 在此先orz小胖子,教我怎么路径压缩链表,那么这样就可以在任意节点跳进链表啦(手动@LCF) 对于查询操作,直接树状数组(以下简称BIT)维护,修改操作就一个个暴力开方搞,再用差值单点更新BIT 不过这样会TLE,要加一点优化对不对,正如开头所说的路径压缩链表 路径压缩链表其实就是个并查集,在普通的链表里,删去两个连续的节点后会是下面这种情况,如删去2,3 当访问 2 的时候,会跳到3,但 3 已经删除了,

[CODEVS 1281] Xn数列

描述 给你6个数,m, a, c, x0, n, g Xn+1 = ( aXn + c ) mod m,求Xn http://codevs.cn/problem/1281/ 分析 比较裸的矩阵乘法题, 好久没做了, 写写思路 假设矩阵 A = { {a1, a2}, {a3, a4} }, B = { {b1, b2}, {b3, b4} }. 根据矩阵乘法的计算方法, 有 : A×B = { {a1b1+a2b2, a1b2+a2b4}, {a3b1+a4b3, a3b2+a4b4} }. 那

Codevs 1257 打砖块

1257 打砖块 http://codevs.cn/problem/1257/ 题目描述 Description 在一个凹槽中放置了n层砖块,最上面的一层有n块砖,第二层有n-1块,……最下面一层仅有一块砖.第i层的砖块从左至右编号为1,2,……i,第i层的第j块砖有一个价值a[i,j](a[i,j]<=50).下面是一个有5层砖块的例子.如果你要敲掉第i层的第j块砖的话,若i=1,你可以直接敲掉它,若i>1,则你必须先敲掉第i-1层的第j和第j+1块砖. 你的任务是从一个有n(n<=5