2 条题解
-
0
思路:第一次写dfs序+树状数组。修改某个节点的值将会影响以他根的子树的值。什么是dfs序呢?就是遍历的顺序。我刚开始节点编号可以用来充当dfs序。结果wrong。只能通过dfs来得到dfs序。然后就是差分了。(原理和洛谷 P3368这个题目一样)初始时,每条边都为1.如果u-v为土路,就为1.那么这个时候就让c[v]=1。全部处理完。修改某个点会造成以他为跟的子节点的值发生改变。所以就是一个区间发生了改变。如果根为1,最大叶子节点编号为3.那么这个区间就是【1,3】。怎么来的呢?就是以当前节点的dfs序为左端点,以当前节点为跟能走到最远(或者最大的为右端点)。这样就是区间修改,单点查询了。详细看代码。
#include<stdio.h> #include<iostream> #include<vector> #include<algorithm> #define MAXN 250005 typedef long long LL; using namespace std; int n,m,tot; vector<int> G[MAXN]; bool vis[MAXN]; int Left[MAXN],Right[MAXN]; int c[MAXN]; int lowbit(int x) { return (x&((-1)*x)); } void add(int x,int d) { while(x<=n) { c[x]+=d; x+=lowbit(x); } } int sum(int x) { int ans=0; while(x>0) { ans+=c[x]; x-=lowbit(x); } return ans; } void dfs(int u,int fa) { vis[u]=true; Left[u]=++tot; //tot=u; for(int i=0;i<G[u].size();i++) { int v=G[u][i]; if(vis[v]) continue; dfs(v,u); } Right[u]=tot; } int main() { scanf("%d",&n); tot=0; int uu,vv; for(int i=1;i<n;i++) { scanf("%d %d",&uu,&vv); G[uu].push_back(vv); G[vv].push_back(uu); } memset(vis,false,sizeof(vis)); dfs(1,-1); for(int i=2;i<=n;i++) { add(Left[i],1); add(Right[i]+1,-1); } scanf("%d",&m); int mm,nn; char ch; for(int i=0;i<n+m-1;i++) { cin>>ch; if(ch=='W') { cin>>mm; printf("%d\n",sum(Left[mm])); } else if(ch=='A') { cin>>mm>>nn; add(Left[nn],-1); add(Right[nn]+1,1); } //getchar(); } return 0; } -
0
#include <bits/stdc++.h> using namespace std; const int N = 250010; int n, c[N]; inline void add(int x, int k) { for (; x <= n; x += (x & -x)) c[x] += k; } inline int getsum(int x) { int res = 0; for (; x; x -= (x & -x)) res += c[x]; return res; } vector<int> G[N]; int l[N], r[N], tsp; // l[i], r[i]分别表示以i为根节点的子树在dfs序中的最左位置和最右位置 void dfs(int x, int xfa) { l[x] = ++tsp; for (int y : G[x]) if (y != xfa) dfs(y, x); r[x] = tsp; } int main() { scanf("%d", &n); for (int i = 1, x, y; i < n; i++) { scanf("%d%d", &x, &y); G[x].push_back(y); G[y].push_back(x); } tsp = 0; dfs(1, 0); memset(c, 0, sizeof(c)); for (int i = 2; i <= n; i++) add(l[i], 1), add(r[i] + 1, -1); int m; scanf("%d", &m); for (int i = 1; i <= m + n - 1; i++) { char c[2]; scanf("%s", c); if (c[0] == 'W') { int x; scanf("%d", &x); printf("%d\n", getsum(l[x])); } else { int x, y; scanf("%d%d", &x, &y); if (l[x] > l[y]) swap(x, y); add(l[y], -1); add(r[y] + 1, 1); } } return 0; }
- 1
信息
- ID
- 2756
- 时间
- 2000ms
- 内存
- 64MiB
- 难度
- 7
- 标签
- 递交数
- 17
- 已通过
- 9
- 上传者