bzoj4564: [Haoi2016]地图 仙人掌的圆方树 莫队 分块
bzoj4564: [Haoi2016]地图
Description
一天rin来到了一个遥远的都市。这个都市有n个建筑,编号从1到n,其中市中心编号为1,这个都市有m条双向通
行的街道,每条街道连接着两个建筑,其中某些街道首尾相连连接成了一个环。rin通过长时间的走访,已经清楚
了这个都市的两个特点:1. 从市中心出发可以到达所有的建筑物。2. 任意一条街道最多存在与一个简单环中。令
rin心花怒放的是,每个建筑物都会有拉面售卖。拉面有很多不同的种类,但对于rin而言只有油腻程度的不同,因
此我们把油腻程度相同的拉面看做同一种拉面。由于不同建筑物的拉面的油腻程度可能不同,我们用一个正整数来
表示拉面的油腻程度。要知道,拉面可是rin的最爱,但是现在到了下班高峰期,都市的交通变得非常的堵塞。 ri
n只能通过没有被堵死的街道通行,去品尝所在建筑物的拉面。现在rin想知道,如果她正在编号为x的建筑物,那
么在从市中心到x的所有简单路径经过的街道都被堵死的情况下,rin可以品尝到的拉面中(注意没有出现的拉面是
不能算在里面的):
- 油腻程度≤ y且品尝次数为奇数次的拉面有多少种?
- 油腻程度≤ y且品尝次数为偶数次的拉面有多少种?
Input
第一行两个正整数n,m,含义如题所示第二行一共N个正整数,第i个数Ai表示第i个建筑物出售的拉面的油腻程度。
接下来M行,每行两个正整数x,y,表示在建筑物x,y之间有一条双向通行的街道。数据保证1<=x<y<=N接下来一行一
个正整数Q,表示询问个数。接下来Q行每行三个非负整数ty,x,y,x表示询问的建筑物编号,y表示油腻程度的限制
,ty=0时表示询问偶数,ty=1表示询问奇数。N<=100000,M<=150000,Q<=100000,Ai<=10^6提示:请注意数据范围中
的<=,特殊条件中提到的??均为询问中的y,对于所有的数据,有y<=10^6
Output
一共Q行,对于每个询问输出一个答案。
Sample Input
10 12
1 10 4 5 2 10 1 8 4 8
1 2
1 3
1 4
2 5
4 6
4 7
7 8
2 9
8 10
1 6
8 10
4 7
10
0 3 9
1 7 6
0 5 2
1 10 9
0 5 7
1 7 4
0 7 3
1 2 7
0 3 4
0 3 8
Sample Output
0
1
0
1
0
1
0
2
0
0
分析
xxx可以走到的节点仙人掌的子树所有节点。
好像仙人掌子树dfs序有一些奇技淫巧来着?
不过我是直接上了圆方树。
剩下的转化为某个区间内小于某个权值的数中出现奇数/偶数次的数的个数。
可以用莫队+分块解决。
做法参见gty的二逼妹子序列
代码
码农题
#include<bits/stdc++.h>
const int N = 2e5 + 10, Bs = 320;
int ri() {char c = getchar(); int x = 0, f = 1; for(;c < '0' || c > '9'; c = getchar()) if(c == '-') f = -1;for(;c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) - '0' + c; return x * f;
}
int a[N], in[N], id[N], b[N], out[N], ps[N], l[N], r[N], A[N], tot;
struct Edge {int pr[N], to[N << 1], nx[N << 1], tp;void add(int u, int v) {to[++tp] = v; nx[tp] = pr[u]; pr[u] = tp;}void adds(int u, int v) {add(u, v); add(v, u);}
};
struct Round_Square_Tree {Edge T; int tot;void dfs(int u, int ff) {in[u] = ++tot; ps[tot] = u;for(int i = T.pr[u]; i; i = T.nx[i])if(T.to[i] != ff) dfs(T.to[i], u);out[u] = tot;}
}rst;
struct Tarjan {Edge G; int fa[N], dfn[N], low[N], st[N], tp, tm;void dfs(int u, int ff) {fa[u] = ff; dfn[u] = low[u] = ++tm; st[++tp] = u;for(int i = G.pr[u], v; i; i = G.nx[i]) if((v = G.to[i]) != ff) {if(!dfn[v]) {dfs(v, u), low[u] = std::min(low[u], low[v]);if(low[v] >= dfn[u]) for(rst.T.adds(u, ++tot); st[tp + 1] != v;)rst.T.adds(st[tp--], tot);}else low[u] = std::min(low[u], dfn[v]); }}
}tar;
struct Block {int cnt[Bs]; int odd, sum;void Ins(int x, int p) {sum -= cnt[x] ? 1 : 0; odd -= cnt[x] & 1; sum += (cnt[x] += p) ? 1 : 0; odd += cnt[x] & 1;}
};
struct Ask {bool t; int l, r, y, id;};
bool cmp(Ask a, Ask c) {return b[a.l] == b[c.l] ? ((b[a.l] & 1) ? a.r < c.r : a.r > c.r) : b[a.l] < b[c.l];
}
struct MT {Block b[Bs]; Ask q[N]; int n;void Add(int x, int p) {int v; if(!(v = a[ps[x]])) return ;b[id[v]].Ins(v - l[id[v]], p);}int Query(int v, int t) {int odd = 0, x = 1, sum = 0; for(;r[x] <= v; ++x) odd += b[x].odd, !t ? sum += b[x].sum : 0;for(int i = l[x];i <= v; ++i) odd += b[x].cnt[i - l[x]] & 1, !t ? (sum += b[x].cnt[i - l[x]] ? 1 : 0) : 0;return t ? odd : sum - odd;}void Work() {std::sort(q + 1, q + n + 1, cmp);int L = 1, R = 0;for(int i = 1;i <= n; ++i) {for(;R < q[i].r;) Add(++R, 1);for(;L > q[i].l;) Add(--L, 1);for(;L < q[i].l;) Add(L++, -1);for(;R > q[i].r;) Add(R--, -1);A[q[i].id] = Query(q[i].y, q[i].t);}}
}mt;
struct Init {int c[N], nn, n, m, B, Q;int F(int x) {if(x < c[1]) return 0;int L = 1, R = nn, m;for(;L != R; c[m = L + R + 1 >> 1] <= x ? L = m : R = m - 1) ;return L;}void Value_Init() {tot = n = ri(); m = ri();for(int i = 1;i <= n; ++i) c[i] = a[i] = ri();std::sort(c + 1, c + n + 1);nn = 1; for(int i = 2;i <= n; ++i) if(c[i] != c[i - 1]) c[++nn] = c[i];for(int i = 1;i <= n; ++i) a[i] = F(a[i]);B = sqrt(nn); for(int i = 1;i <= nn; ++i) {id[i] = (i - 1) / B + 1;if(!l[id[i]]) l[id[i]] = i; r[id[i]] = i;}r[id[nn] + 1] = l[id[nn] + 1] = nn + 1;}void Tree_Init() {for(;m--;) tar.G.adds(ri(), ri());tar.dfs(1, 0); rst.dfs(1, 0);B = sqrt(tot) + 1;for(int i = 1;i <= tot; ++i) b[i] = (i - 1) / B + 1;Q = ri();for(int i = 1;i <= Q; ++i) {int t = ri(), u = ri(), y = ri();y = F(y); if(!y) continue;mt.q[++mt.n] = (Ask) {t, in[u], out[u], y, i};}}
}pre;
int main() {pre.Value_Init(); pre.Tree_Init();mt.Work();for(int i = 1;i <= pre.Q; ++i) printf("%d\n", A[i]);return 0;
}
bzoj4564: [Haoi2016]地图 仙人掌的圆方树 莫队 分块相关推荐
- P3180-[HAOI2016]地图【圆方树,莫队,分块】
正题 题目链接:https://www.luogu.com.cn/problem/P3180 题目大意 nnn个点mmm条边的一个仙人掌,有点权. QQQ次询问给出op,x,yop,x,yop,x,y ...
- 【CodeForces】700 D. Huffman Coding on Segment 哈夫曼树+莫队+分块
[题目]D. Huffman Coding on Segment [题意]给定n个数字,m次询问区间[l,r]的数字的哈夫曼编码总长.1<=n,m,ai<=10^5. [算法]哈夫曼树+莫 ...
- 仙人掌与圆方树的学习 【模板】静态仙人掌
题目链接 BZOJ 2125 最短路 圆方树 求一幅仙人掌图中,Q次询问两点最短路. 仙人掌问题,我们可以直接将原来的N个点缩点成为一棵生成树--圆方树. 这棵圆方树是怎样建立的呢,首先,我们看图: ...
- 洛谷 :P5236 【模板】静态仙人掌(圆方树模板 + 仙人掌最短路)
题意很简单,在仙人掌图上求两点的最短路. 做法:需要用到圆方树 先来看看什么是圆方树:圆方树,就是由仙人掌图转化而来,树上分两种点:圆点和方点,圆点是仙人掌图上的点,方点是由仙人掌的环转化而来. 由于 ...
- 仙人掌相关问题的解法(1)-DFS树解决仙人掌DP问题,圆方树
前言 有难度的仙人掌题在近几年也只是在国家集训队水平的比赛里才会出现. 不过,这不是说仙人掌对国集水平以下的选手意义不大: 首先,仙人掌暴力 DP 问题难度并不大,在省选. NOI 甚至 NOIP 中 ...
- [学习笔记]圆方树广义圆方树
引入 偶尔,我们会遇到一些要在无向图/仙人掌上做的问题,这些问题如果在树上就会比较方便,那么我们就开始考虑能不能把原图等效成一棵树,然后就可以方便地乱搞了? 圆方树就是一种将无向图/仙人掌变成树的数据 ...
- [XSY] 绿色(圆方树、树形DP、树上差分)
绿色 题意简述 题解 首先,每次修改完点权后,重新考虑一遍所有路径显然是不现实的,所以我们考虑求出经过每个点的两端同色的简单路径数,这样权值和容易统计和修改. 接下来分析仙人掌上的简单路径性质.一条简 ...
- 仙人掌圆方树学习笔记
终于对仙人掌有了一点初步的理解. 仙人掌 仙人掌是什么? 仙人掌是一个无向图. 仙人掌有什么特点? 仙人掌的每条边只属于一个简单环. 下面是一个栗子 有什么用呢? 我们可以先用\(tarjan\)找出 ...
- P5236 【模板】静态仙人掌(仙人掌圆方树)
无向仙人掌图 一般需要重构成 仙人掌有向树 然后我们 就考虑 圆点的 方点的不同讨论 这个题是查询两点间最短路 如果lca 是圆点 那么就是 d[a]+d[b]-2*d[lca] 如果是方点 我们需要 ...
最新文章
- Linux shell 学习笔记(11)— 理解输入和输出(标准输入、输出、错误以及临时重定向和永久重定向)
- thinkJava@第五章@隐藏实施过程
- 【Linux多线程】三个经典同步问题
- [剑指offer]面试题3:二维数组中的查找
- 用随机整数填充缺失值_输入一个整数值并在C中用零填充进行打印
- jlist放jbutton 按钮事件失效_电动高处作业吊篮操作如何面对一些突发事件
- DSSM、CNN-DSSM、LSTM-DSSM等深度学习模型在计算语义相似度上的应用+距离运算
- 27 SD配置-主数据-信用管理-定义风险类别
- geoserver发布瓦片数据_OpenLayers教程十八:多源数据加载之矢量切片
- oopc——3.封装
- java常用api简单统计
- 总结之:CentOS 6.5基于DHCP的PXE自动化安装系统详解
- 变量函数命令 - Hugarian , Camel Pascal
- 俄罗斯方块Python
- spring data jpa 条件分页查询
- ArcGIS影像空值填充\插补
- STVD cpstm8 miss } in struct/union definition
- ue4蓝图碰撞检测的类型_UE4蓝图碰撞检测解析
- 软件设计实验一 UML建模实验
- 透明网桥(计算机网络)