BZOJ 2038 小Z的袜子(hose) 莫队算法
来源:互联网 发布:颜值测试软件 编辑:程序博客网 时间:2024/06/11 08:34
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2038
题意:
Description
作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿。终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命……
具体来说,小Z把这N只袜子从1到N编号,然后从编号L到R(L 尽管小Z并不在意两只袜子是不是完整的一双,甚至不在意两只袜子是否一左一右,他却很在意袜子的颜色,毕竟穿两只不同色的袜子会很尴尬。
你的任务便是告诉小Z,他有多大的概率抽到两只颜色相同的袜子。当然,小Z希望这个概率尽量高,所以他可能会询问多个(L,R)以方便自己选择。
Input
输入文件第一行包含两个正整数N和M。N为袜子的数量,M为小Z所提的询问的数量。接下来一行包含N个正整数Ci,其中Ci表示第i只袜子的颜色,相同的颜色用相同的数字表示。再接下来M行,每行两个正整数L,R表示一个询问。
Output
包含M行,对于每个询问在一行中输出分数A/B表示从该询问的区间[L,R]中随机抽出两只袜子颜色相同的概率。若该概率为0则输出0/1,否则输出的A/B必须为最简分数。(详见样例)
Sample Input
6 4
1 2 3 3 3 2
2 6
1 3
3 5
1 6
1 2 3 3 3 2
2 6
1 3
3 5
1 6
Sample Output
2/5
0/1
1/1
4/15
0/1
1/1
4/15
思路:学习莫队算法的第一题,感觉莫队算法是一个姿势优美的暴力程序~
直接分块:
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>using namespace std;typedef long long ll;const int N = 50010;struct node{ int l, r, id;}g[N];int n, m, unit;int a[N], b[N], num[N];ll tmp, ax[N], bx[N];bool cmp(node a, node b){ return a.l/unit != b.l/unit ? a.l/unit < b.l/unit :a.r < b.r;}void add(int i){ tmp -= (ll)num[i] * num[i]; num[i]++; tmp += (ll)num[i] * num[i];}void del(int i){ tmp -= (ll)num[i] * num[i]; num[i]--; tmp += (ll)num[i] * num[i];}ll gcd(ll a, ll b){ if(b == 0) return a; else return gcd(b, a % b);}void solve(){ unit = (int)sqrt(n); sort(g+1, g+1+m, cmp); memset(num, 0, sizeof num); int l = 1, r = 0; tmp = 0; for(int i = 1; i <= m; i++) { while(r < g[i].r) add(a[++r]); while(r > g[i].r) del(a[r--]); while(l < g[i].l) del(a[l++]); while(l > g[i].l) add(a[--l]); ll tmp1 = tmp - (r - l + 1), tmp2 = (ll)(r - l + 1) * (r - l); ll ans = gcd(tmp1, tmp2); ax[g[i].id] = tmp1 / ans, bx[g[i].id] = tmp2 / ans; } for(int i = 1; i <= m; i++) printf("%lld/%lld\n", ax[i], bx[i]);}int main(){ scanf("%d%d", &n, &m); for(int i = 1; i <= n; i++) scanf("%d", &a[i]), b[i] = a[i]; sort(b+1, b+1+n); for(int i = 1; i <= n; i++) a[i] = lower_bound(b+1, b+1+n, a[i]) - b; for(int i = 1; i <= m; i++) scanf("%d%d", &g[i].l, &g[i].r), g[i].id = i; solve(); return 0;}
以曼哈顿距离最小生成树为基础的:
#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>#include <vector>#include <cmath>using namespace std;typedef long long ll;const int N = 50010;const int INF = 0x3f3f3f3f;struct node{ int x, y, id;}p[N], pp[N];struct edge{ int v, u, d;}g[N*10];struct graph{ int to, next;}gra[N*4];struct BIT{ int minn, pos; void init() { minn = INF, pos = -1; }}bit[N];int n, m, a[N], tot;int par[N];int cnt, head[N];int num[N];ll tmp;bool cmp(node a, node b){ if(a.x != b.x) return a.x < b.x; else return a.y < b.y;}bool cmpg(edge a, edge b){ return a.d < b.d;}int ser(int x){ int r = x, i = x, j; while(r != par[r]) r = par[r]; while(par[i] != r) j = par[i], par[i] = r, i = j; return r;}int ask(int i, int m){ int minn = INF, pos = -1; while(i <= m) { if(bit[i].minn < minn) minn = bit[i].minn, pos = bit[i].pos; i += i & -i; } return pos;}void update(int i, int val, int pos){ while(i > 0) { if(val < bit[i].minn) bit[i].minn = val, bit[i].pos = pos; i -= i & -i; }}void add_edge(int v, int u, int d){ g[tot].v = v, g[tot].u = u, g[tot++].d = d;}void _add_edge(int v, int u){ gra[cnt].to = u, gra[cnt].next = head[v], head[v] = cnt++;}void mmst(int n, node p[]){ int a[N], b[N]; tot = 0; for(int i = 0; i < 4; i++) { if(i == 1 || i == 3) { for(int j = 0; j < n; j++) swap(p[j].x, p[j].y); } else if(i == 2) { for(int j = 0; j < n; j++) p[j].x = -p[j].x; } sort(p, p + n, cmp); for(int j = 0; j < n; j++) a[j] = b[j] = p[j].y - p[j].x; sort(b, b + n); int m = unique(b, b + n) - b; for(int j = 1; j <= m; j++) bit[j].init(); for(int j = n - 1; j >= 0; j--) { int pos = lower_bound(b, b + m, a[j]) - b + 1; int ans = ask(pos, m); if(ans != -1) add_edge(p[j].id, p[ans].id, abs(p[j].x - p[ans].x) + abs(p[j].y - p[ans].y)); update(pos, p[j].x + p[j].y, j); } } cnt = 0; memset(head, -1, sizeof head); for(int i = 0; i < n; i++) par[i] = i; sort(g, g + tot, cmpg); for(int i = 0; i < tot; i++) { int fv = ser(g[i].v), fu = ser(g[i].u); if(fv != fu) { par[fv] = fu; _add_edge(g[i].v, g[i].u); _add_edge(g[i].u, g[i].v); } }}struct Ans{ ll a, b;}ans[N];void cal(int l, int r, int d){ for(int i = l; i <= r; i++) { tmp -= (ll)num[a[i]] * num[a[i]]; num[a[i]] += d; tmp += (ll)num[a[i]] * num[a[i]]; }}void dfs(int l1, int r1, int l2, int r2, int idx, int pre){ if(l2 < l1) cal(l2, l1 - 1, 1); if(r2 > r1) cal(r1 + 1, r2, 1); if(l2 > l1) cal(l1, l2 - 1, -1); if(r2 < r1) cal(r2 + 1, r1, -1); ans[pp[idx].id].a = tmp - (r2 - l2 + 1); ans[pp[idx].id].b = (ll)(r2 - l2 + 1) * (r2 - l2); for(int i = head[idx]; i != -1; i = gra[i].next) { int u = gra[i].to; if(pre == u) continue; dfs(l2, r2, pp[u].x, pp[u].y, u, idx); } if(l2 < l1) cal(l2, l1 - 1, -1); if(r2 > r1) cal(r1 + 1, r2, -1); if(l2 > l1) cal(l1, l2 - 1, 1); if(r2 < r1) cal(r2 + 1, r1, 1);}ll gcd(ll a, ll b){ if(b == 0) return a; else return gcd(b, a % b);}int main(){ while(~ scanf("%d%d", &n, &m)) { for(int i = 1; i <= n; i++) scanf("%d", &a[i]); for(int i = 0; i < m; i++) { scanf("%d%d", &p[i].x, &p[i].y); p[i].id = i; pp[i] = p[i]; } mmst(m, p); memset(num, 0, sizeof num); tmp = 0; dfs(1, 0, pp[0].x, pp[0].y, 0, -1); for(int i = 0; i < m; i++) { ll d = gcd(ans[i].a, ans[i].b); printf("%lld/%lld\n", ans[i].a / d, ans[i].b / d); } } return 0;}
0 0
- 小Z的袜子(hose) - bzoj 2038 莫队算法
- BZOJ 2038 小Z的袜子(hose) 莫队算法
- BZOJ-2038 小Z的袜子(hose) (莫队算法)
- BZOJ 2038 小Z的袜子(hose) [莫队算法]
- BZOJ 2038([2009国家集训队]小Z的袜子(hose)-莫队算法序列)
- BZOJ 2038 2009国家集训队 小Z的袜子(hose) 莫队算法
- bzoj 2038: [2009国家集训队]小Z的袜子(hose) (莫队算法)
- BZOJ 2038: [2009国家集训队]小Z的袜子(hose)|分块|莫队算法
- BZOJ 2038: [2009国家集训队]小Z的袜子(hose)(莫队算法)
- BZOJ 2038 小Z的袜子(hose)(莫队算法)
- BZOJ-2038 小Z的袜子(hose) 莫队算法
- BZOJ 2038 小Z的袜子(hose)(莫队算法)
- bzoj 2038: [2009国家集训队]小Z的袜子(hose) 【莫队算法】
- bzoj 2038: [2009国家集训队]小Z的袜子(hose)(莫队算法)
- bzoj 2038: [2009国家集训队]小Z的袜子(hose) 莫队算法
- bzoj 2038 [2009国家集训队]小Z的袜子(hose)(莫队算法)
- [BZOJ]2038: [2009国家集训队]小Z的袜子(hose) 莫队算法
- BZOJ 2038 [2009国家集训队]小Z的袜子(hose)题解 莫队算法
- J2EE使用hibernate存储和显示BLOB图片(从页面到数据库)
- web前端CSS开发中的10个不要
- 【连载】研究EasyUI系统——控件构造形式
- mybatis foreach
- Makefile之学习总结(3)--- Makefile (v2.0)
- BZOJ 2038 小Z的袜子(hose) 莫队算法
- Ubuntu下MySQL的安装、配置、启动、停止、重启、乱码问题
- java源码:LinkedHashMap
- unity3d 25
- 16-08-05道路
- 两个栈实现一个队列
- iOS集成极光推送,绕过一些坑
- [HDU5799] This world need more Zhu [2016 Multi-University Training Contest 6(2016多校联合训练2) 1007]
- 迷宫求解java解决方案