bzoj 1103

题目大意:有一棵树根为1,刚开始每条边的权值为1,  现在有m + n - 1 个操作, A :x  y  , 将x和y相连的边权值变为1, W:x, 询问x到1路径上的权值和。

思路 : 方法一: 用dfs序建立树状数组, 每个点入栈位置的值为1, 出栈为-1, 询问的值就是sum( l [ x ] ), 修改就将出栈,入栈的点全部变成1, 巧妙的地方在于

利用dfs序求前缀和会把不是在这条链上的边全部抵消掉。

方法二:用dfs序建立线段数, 线段数里每个点表示该点到1的权值和, 修改一条边相当于把该边下边的子树的值全部减1, 相当于区间修改。

 1 #include<bits/stdc++.h>
 2 #define LL long long
 3 #define fi first
 4 #define se second
 5 #define mk make_pair
 6 #define pii pair<int,int>
 7
 8 using namespace std;
 9
10 const int N=5e5+7;
11 const int M=1e4+7;
12 const int inf=0x3f3f3f3f;
13 const LL INF=0x3f3f3f3f3f3f3f3f;
14 const int mod=1e9 + 7;
15
16 int n, m, tot, st[N], l[N], r[N];
17
18 struct BIT {
19     int a[N];
20     void modify(int pos, int v) {
21         for(int i = pos; i <= tot; i += i & -i)
22             a[i] += v;
23     }
24
25     int sum(int pos) {
26         int ans = 0;
27         for(int i = pos; i; i -= i & -i)
28             ans += a[i];
29         return ans;
30     }
31 }bit;
32
33 vector<int> edge[N];
34 void dfs(int u) {
35     l[u] = ++tot;
36     for(int i = 0; i < edge[u].size(); i++) {
37         int v = edge[u][i];
38         dfs(v);
39     }
40     r[u] = ++tot;
41 }
42 int main() {
43     scanf("%d", &n);
44     for(int i = 1; i < n; i++) {
45         int u, v; scanf("%d%d", &u, &v);
46         if(u > v) swap(u, v);
47         edge[u].push_back(v);
48     }
49     dfs(1);
50     for(int i = 1; i <= n; i++) {
51         bit.modify(l[i], 1);
52         bit.modify(r[i], -1);
53     }
54     scanf("%d", &m);
55     m += n - 1;
56     while(m--) {
57         char s[5]; scanf("%s", s);
58         if(s[0] == ‘A‘) {
59             int u, v; scanf("%d%d", &u, &v);
60             if(u > v) swap(u, v);
61             bit.modify(l[v], -1);
62             bit.modify(r[v], 1);
63         } else {
64             int x; scanf("%d", &x);
65             printf("%d\n", bit.sum(l[x]) - 1);
66         }
67     }
68     return 0;
69 }
70 /*
71 */

原文地址:https://www.cnblogs.com/CJLHY/p/9005054.html

时间: 2024-11-05 13:32:14

bzoj 1103的相关文章

【BZOJ 1103】 [POI2007]大都市meg

1103: [POI2007]大都市meg Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 1292  Solved: 660 [Submit][Status] Description 在经济全球化浪潮的影响下,习惯于漫步在清晨的乡间小路的邮递员Blue Mary也开始骑着摩托车传递邮件了.不过,她经常回忆起以前在乡间漫步的情景.昔日,乡下有依次编号为1..n的n个小村庄,某些村庄之间有一些双向的土路.从每个村庄都恰好有一条路径到达村庄1(即比特

[BZOJ 1103][POI 2007]大都市(DFS求拓扑序+树状数组)

题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1103 题目大意:给你一个树,刚开始所有树边边权均为1,不断地将其中的某些边边权改为0,其间问你某个点到根节点之间路径上的边权和. 此题和POJ的Apple Tree很相近... 首先DFS生成整棵树的拓扑序,DFS时每个结点i进入的时间l[i]和离开的时间r[i],然后对每次更改操作,维护树状数组即可. #include <iostream> #include <stdi

【POI2007】【Bzoj 1103】大都市meg

http://www.lydsy.com/JudgeOnline/problem.php?id=1103 在线查询某点到根节点的点权和,参考DFS序&欧拉序列,用树状数组维护即可O(nlogn) // <meg.cpp> - Sun Oct 2 08:13:38 2016 // This file is made by YJinpeng,created by XuYike's black technology automatically. // Copyright (C) 2016 C

bzoj 1103: [POI2007]大都市meg

1103: [POI2007]大都市meg Description 在经济全球化浪潮的影响下,习惯于漫步在清晨的乡间小路的邮递员Blue Mary也开始骑着摩托车传递邮件了. 不过,她经常回忆起以前在乡间漫步的情景.昔日,乡下有依次编号为1..n的n个小村庄,某些村庄之间有一些双 向的土路.从每个村庄都恰好有一条路径到达村庄1(即比特堡).并且,对于每个村庄,它到比特堡的路径恰好 只经过编号比它的编号小的村庄.另外,对于所有道路而言,它们都不在除村庄以外的其他地点相遇.在这个未开 化的地方,从来

数据结构(线段树):BZOJ 1103 [POI2007]大都市meg

1103: [POI2007]大都市meg Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1791  Solved: 925[Submit][Status][Discuss] Description 在经济全球化浪潮的影响下,习惯于漫步在清晨的乡间小路的邮递员Blue Mary也开始骑着摩托车传递邮件了. 不过,她经常回忆起以前在乡间漫步的情景.昔日,乡下有依次编号为1..n的n个小村庄,某些村庄之间有一些双 向的土路.从每个村庄都恰好有一条路径

BZOJ 1103: [POI2007]大都市meg( 树链剖分 )

早上数学考挂了...欲哭无泪啊下午去写半个小时政治然后就又可以来刷题了.. 树链剖分 , 为什么跑得这么慢... --------------------------------------------------------------------- #include<cstdio> #include<algorithm> #include<iostream> #include<cstring> #define rep( i , n ) for( int

BZOJ 1103 大都市(dfs序+树状数组)

应该是一道很水的题吧... 显然可以用树链剖分解决这个问题,虽然不知道多一个log会不会T.但是由于问题的特殊性. 每次修改都是将边权为1的边修改为0,且询问的是点i到根节点的路径长度. 令点i到根节点的路径长度为w[i],显然初始时w[i]=dep[i].考虑修改边为(u,v),那么令u为深度大的点. 那么u的子树的所有答案就要减1.考虑dfs序,则每次需要修改的是一段连续的区间. 树状数组维护单点查询,区间修改,美滋滋. # include <cstdio> # include <c

BZOJ 1103 大都市

dfs序+BIT. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxv 250050 #define maxe 500500 using namespace std; int n,x,y,m,g[maxv],nume=0,w[maxv],mx[maxv],dis[maxv],val[maxv],fath[maxv],times=0; ch

BZOJ 1103 POI 2007 大都市meg 树状数组

题目大意:给出一棵树,一开始每两个点之间都是由土路连接的,但是会有一些土路逐渐变成公路,问每次从点1开始到点k有多少土路. 思路:POI不怎么难的题,实际上每个点到1的土路的数量就是这个点的深度,在土路变成公路的时候,这个点以及子树的所有节点的深度都要-1,子树修改就很基本了,可以用DFS序+fenwick,当然要是不嫌麻烦也可以树链剖分,但是常数会比较卡.. CODE: #include <cstdio> #include <cstring> #include <iostr