hdu4638 Group(树状数组)
2015-08-27 14:16
197 查看
题目大意:
给一个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)。否则不进行操作。
具体更新代码
在这个更新基础上,查询就只要直接用树状数组查询区间合就好了。
最后附上全部代码:
给一个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;
}
相关文章推荐
- 表单样式
- 边框样式
- loadrunner自带web server 无法启动
- (备份)java 弹出退出提示框 lua调用
- 第四章 数据的概括性度量
- 利用余弦相似度做文本分类
- Weblogic中已部署好的项目,突然部署失败问题
- vsphere之vmotion精华
- 将博客搬至CSDN
- 一篇牛X的文章,先收后读
- 【数论】君と彼女の恋
- ios键盘监听键盘弹出,不会档住UITextField
- oracle datafile 生成查询树
- sqlserver注册表清理
- oauth2.0在监控宝项目中的应用一例
- nginx的rewrite相关知识
- nginx的rewrite相关知识
- 背景属性
- 收集android上开源的酷炫的交互动画和视觉效果:Interactive-animation
- SqlMapConfig.xml中的setting属性