HDU 4638 Groub 线段树离线,莫队,分块法
来源:互联网 发布:阿里云短信接口 php 编辑:程序博客网 时间:2024/05/22 03:40
题意:找到区间里有多少组连续数字串。
PS:由于网上关于这个题的解法非常多,不懂自己去看,我自己写了3种解法,主要比较效率。
解法1: 询问离线,右端点排序,树状数组(线段树维护)
//7876kb, 795ms, 1331kb
#include <bits/stdc++.h>using namespace std;const int maxn = 1e6+7;int T, n, m, a[maxn], p[maxn], ans[maxn];struct node{ int l, r, id; node(){} node(int l, int r, int id) : l(l), r(r), id(id){} bool operator < (const node &rhs) const{ return r < rhs.r; }}q[maxn];namespace BIT{ int c[maxn]; void init(){memset(c, 0, sizeof(c));} inline int lowbit(int x){return x&-x;} inline void add(int i, int v){for(; i<= n; i += lowbit(i)) c[i] += v;} inline query(int i){int res = 0; for(; i; i -= lowbit(i)) res += c[i]; return res;}}using namespace BIT;int main(){ scanf("%d", &T); while(T--){ scanf("%d%d", &n, &m); for(int i = 1; i <= n; i++){ scanf("%d", &a[i]); p[a[i]] = i; } for(int i = 1; i <= m; i++){scanf("%d%d", &q[i].l, &q[i].r); q[i].id = i;} sort(q + 1, q + m + 1); init(); int j = 1; for(int i = 1; i <= n; i++){ add(i, 1); if(a[i] > 1 && p[a[i] - 1] < i) add(p[a[i] - 1], -1); if(a[i] < n && p[a[i] + 1] < i) add(p[a[i] + 1], -1); while(j <= m && q[j].r == i){ ans[q[j].id] = query(q[j].r) - query(q[j].l - 1); j++; } } for(int i = 1; i <= m; i++) printf("%d\n", ans[i]); } return 0;}
解法2:莫队 O(n^1.5)
//4944 kb, 1060ms, 1287b
#include <bits/stdc++.h>using namespace std;const int maxn = 1e6+7;int T, n, m, a[maxn], pos[maxn], Ans[maxn], ans;struct node{ int l, r, id; node(){} node(int l, int r, int id) : l(l), r(r), id(id){}}q[maxn];bool vis[maxn];bool cmp(node a, node b){ if(pos[a.l] == pos[b.l]) return a.r < b.r; return pos[a.l] < pos[b.l];}void update(int x, int d){ vis[x] = d; if(d) ans += 1 - vis[x + 1] - vis[x - 1]; else ans += vis[x + 1] + vis[x - 1] - 1;}int main(){ scanf("%d", &T); while(T--){ scanf("%d%d", &n, &m); memset(vis, 0, sizeof(vis)); int block = sqrt(n); for(int i = 1; i <= n; i++){ scanf("%d", &a[i]); pos[i] = (i - 1) / block; } for(int i = 1; i <= m; i++){scanf("%d%d", &q[i].l, &q[i].r); q[i].id = i;} sort(q + 1, q + m + 1, cmp); int L = 1, R = 0; ans = 0; for(int i = 1; i <= m; i++){ int id = q[i].id; while(R < q[i].r) R++, update(a[R], 1); while(R > q[i].r) update(a[R], 0), R--; while(L < q[i].l) update(a[L], 0), L++; while(L > q[i].l) L--, update(a[L], 1); Ans[id] = ans; } for(int i = 1; i <= m; i++) printf("%d\n", Ans[i]); } return 0;}
解法3:分块 (话说这个分块真的不是莫队???毛啊,这就是瞎暴力吧???) O(n^1.5)
//951ms 920kb 2085b
#include <bits/stdc++.h>using namespace std;const int maxn = 1e6+7;int T, n, m, L, R, a[maxn], Ans[maxn], ans;bool vis[maxn];struct node{ int l, r, id, belong; node(){} node(int l, int r, int id, int belong) : l(l), r(r), id(id), belong(belong) {} bool operator < (const node &rhs) const{ if(belong == rhs.belong) return r < rhs.r; return belong < rhs.belong; }}q[maxn];void query(int x, int y, int type){ if(type == 1){ ans = 0; for(int i = x; i <= y; i++){ vis[a[i]] = 1; if(vis[a[i] - 1] && vis[a[i] + 1]) ans--; else if(!vis[a[i] - 1] && !vis[a[i] + 1]) ans++; } } else{ for(int i = x; i < L; i++){ vis[a[i]] = 1; if(vis[a[i] - 1] && vis[a[i] + 1]) ans--; else if(!vis[a[i] - 1] && !vis[a[i] + 1]) ans++; } for(int i = R + 1; i <= y; i++){ vis[a[i]] = 1; if(vis[a[i] - 1] && vis[a[i] + 1]) ans--; else if(!vis[a[i] - 1] && !vis[a[i] + 1]) ans++; } for(int i = L; i < x; i++){ vis[a[i]] = 0; if(vis[a[i] - 1] && vis[a[i] + 1]) ans++; else if(!vis[a[i] - 1] && !vis[a[i] + 1]) ans--; } for(int i = y + 1; i <= R; i++){ vis[a[i]] = 0; if(vis[a[i] - 1] && vis[a[i] + 1]) ans++; else if(!vis[a[i] - 1] && !vis[a[i] + 1]) ans--; } } L = x, R = y;}int main(){ scanf("%d", &T); while(T--){ scanf("%d%d", &n, &m); int block = sqrt(n); for(int i = 1; i <= n; i++) scanf("%d", &a[i]); for(int i = 1; i <= m; i++){ scanf("%d%d", &q[i].l, &q[i].r); q[i].belong = q[i].l / block; q[i].id = i; } sort(q + 1, q + m + 1); memset(vis, 0, sizeof(vis)); ans = 0; for(int i = 1; i <= m; i++){ query(q[i].l, q[i].r, i); Ans[q[i].id] = ans; } for(int i = 1; i <= m; i++){ printf("%d\n", Ans[i]); } } return 0;}
0 0
- HDU 4638 Groub 线段树离线,莫队,分块法
- hdu 4638 Group(离线线段树)
- hdu 4638 Group (线段树+离线处理)
- HDU 4417 离线线段树
- HDU 3333 离线线段树
- HDU 3874 离线线段树
- [ZOJ 3633]Alice's present 离线分块/线段树
- hdu 4366 分块 or 线段树。
- hdu 4638 Group 线段树/数状数组+离线
- hdu 4638 Group (莫队算法 || 离线线段树)
- hdu 4638 Group(莫队算法|离线线段树)
- hdu 4417 线段树离线处理
- hdu 4348 线段树离线处理
- HDU 3333 & 3874 (线段树+离线询问)
- HDU 4417 Super Mario(离线线段树)
- HDU 4902 Nice boat 线段树+离线
- HDU 4031 Attack(离线+线段树)
- hdu 4288 线段树+离线+离散化
- UVa 10976 Fractions Again?! 【暴力】【基础】
- Redis系统
- 2017年最值得关注的设计趋势
- 补2016.2.21
- React Native学习笔记(4)--Navigator
- HDU 4638 Groub 线段树离线,莫队,分块法
- 数据结构实验之排序八:快速排序
- “人生没有一桩幸福不要付代价的。东边占了便宜,西边就得吃亏些。”--《傅雷家书》
- Mybatis Generator最完整配置详解
- 使用Crashlytics收集iOS崩溃报告
- group by分组内排序,取其中一条
- 软件开发者的精力管理(一)
- JQuery UI Autocomplete
- A Java Runtime Environment (JRE) or Java Development Kit (JDK)