hdu4638 Group(树状数组)
来源:互联网 发布:java下载和安装 编辑:程序博客网 时间:2024/05/22 00:42
题目大意:
给一个1-n的排列,然后询问[x,y]区间中有多少个连续的段。
如给一个3 1 2 5 4, 查询是2 4,那么就是问1 2 5中有多少个连续的串,一共有两个串,1、2为一个串,5为一个串
若查询是2 5,则问的是1 2 5 4中有多少个连续的串,一共有两个串, 1、2为一个串, 4、5 为一个串。
反思:这一题我想了蛮久的,因为我一直想要去维护每一个串的首个数字,但想了很久都没有想到维护的方法。
后面看了题解后才发现,不仅仅可以通过数串数得到答案,还可以通过一段区间中有多少个相邻的数字对,来得到答案。
若查询区间中有k个相邻数字对,区间长度是m,那么这次的答案就是m - k。
这个其实蛮好理解的,大家举几个例子仔细想一下就明白了。
像1 2 5 4,其中1和2、4和5是相邻的数字对,所以答案就是 4 - 2 = 2
现在问题就变成了求一段区间当中有多少个相邻的数字对。
我的解决方法是进行离线查询,对m个询问按照x的大小,从大到小排序,然后根据查询,依次更新区间[n, n], [n-1, n]. [n-2, n] , [n-3, n], [n-4, n] ........ [2, n], [1, n]的数字对的情况:
具体更新方法:从[i+1, n]更新到[i, n],若pos[a[i]+1] > i , 则updata(pos[a[i]+1], 1)。若pos[a[i]-1] > i ,则updata(pos[a[i-1]]. 1)。否则不进行操作。
具体更新代码
void updata(int val, int posx){if (val != n)if (pos[val+1] > posx)updata_tree(pos[val+1], 1);if (val != 1)if (pos[val-1] > posx)updata_tree(pos[val-1], 1);return ;}
j = n + 1;for (i=m; i>=1; i--){while (j > q[i].x){j --;updata(a[j], j);}ans[q[i].id] = (q[i].y - q[i].x + 1) - query(q[i].x, q[i].y);}
在这个更新基础上,查询就只要直接用树状数组查询区间合就好了。
最后附上全部代码:
#include <iostream>#include <stdio.h>#include <stdlib.h>#include <algorithm>using namespace std;const int MAXN = 1e5 + 100;class query{public:int id, x, y;};bool operator < (const query &a, const query &b){return a.x < b.x;}query q[MAXN];int a[MAXN], pos[MAXN], ans[MAXN], h[MAXN];int n, m;int lowbit(int x){return x&(-x);}void updata_tree(int x, int val){while (x <= n){h[x] += val;x += lowbit(x);}return;}int query_tree(int x){int ans = 0;if (x == 0)return 0;while (x > 0){ans += h[x];x -= lowbit(x);}return ans;}void updata(int val, int posx){if (val != n)if (pos[val+1] > posx)updata_tree(pos[val+1], 1);if (val != 1)if (pos[val-1] > posx)updata_tree(pos[val-1], 1);return ;}int query(int x, int y){int ans;ans = query_tree(y) - query_tree(x-1);return ans;}int main(){int T, i, j;scanf("%d",&T);while (T--){scanf("%d%d",&n,&m);for (i=1; i<=n; i++){scanf("%d", &a[i]);pos[a[i]] = i;h[i] = 0;}for (i=1; i<=m; i++){scanf("%d%d",&q[i].x, &q[i].y);q[i].id = i;}sort(q+1, q+m+1);j = n + 1;for (i=m; i>=1; i--){while (j > q[i].x){j --;updata(a[j], j);}ans[q[i].id] = (q[i].y - q[i].x + 1) - query(q[i].x, q[i].y);}for (i=1; i<=m; i++)printf("%d\n", ans[i]);}return 0;}
0 0
- hdu4638 Group(树状数组)
- Group(hdu4638,树状数组)
- HDU4638——Group(树状数组+离线操作)
- HDU4638【离线树状数组】
- [HDU4638]Group(莫队)
- hdu4638 Group(离线线段树)
- HDU4638 Group (线段树,莫队算法)
- hdu 多校contest4 group(树状数组)
- hdu 4638 Group (树状数组+离线)
- HDU 4638 Group(离线 + 树状数组)
- hdu 4638 Group(树状数组)
- hdu 4638 Group 树状数组
- HDU 4638 Group(树状数组)
- 【树状数组】 HDOJ 4638 Group
- HDU 4638 Group (树状数组)
- hdu-4638-Group-(树状数组,离线操作)
- HDU4638:Group(线段树离线处理)
- Hdu 4638 Group 离线+树状数组
- openwrt 目录说明
- fastjson
- js全部替换replaceAll
- java实现区域内屏幕截图示例
- Fiddler 学习(二)
- hdu4638 Group(树状数组)
- 设计模式: 自己手动写一个代理模式
- php正则表达式以及正则函数详解
- tomcat 配置web项目的方法
- MySQL数据库设置远程访问权限方法小结 简单,粗暴,有截图
- 在 Ubuntu 用UVC支持 使用 WebCam摄像头传感器
- android 初级__进阶__总结_转载
- spring(13) spring整合hibernate
- first blood