HDOJ 5654 xiaoxin and his watermelon candy(离线+树状数组)
Posted 小胡子Haso
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDOJ 5654 xiaoxin and his watermelon candy(离线+树状数组)相关的知识,希望对你有一定的参考价值。
【HDOJ 5654】 xiaoxin and his watermelon candy(离线+树状数组)
xiaoxin and his watermelon candy
Time Limit: 4000/4000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 233 Accepted Submission(s): 61
xiaoxin is very smart since he was a child. He arrange these candies in a line and at each time before eating candies, he selects three continuous watermelon candies from a specific range [L, R] to eat and the chosen triplet must satisfies:
if he chooses a triplet
1.
2.
Your task is to calculate how many different ways xiaoxin can choose a triplet in range [L, R]?
two triplets
For each test case, the first line contains a single integer
The third line is an integer
1 5 1 2 3 4 5 3 1 3 1 4 1 5
1 2 3
题目大意:有n个糖果,从左到右列出每个糖果的甜度
之后有Q次查询,每次查询[L,R]中三元组的个数
这个三元组要求满足为连续的三个值,然后这三个值为非递减。
问[L,R]中不重复的三元组的个数。重复表示三元组中三个数均对影响等。如果重复则只记一次
正解为主席树………………额………………恩…………
搜到这个离线+树状数组的写法,给大家分享下
思路很巧妙。先离线存储所有查询。
然后对查询进行排序,以右边界从小到大排序。
然后从1到n开始枚举位置pos
每到一个位置,看一下从当前往后连续的三个满不满足题目中三元组的要求,如果满足,在树状数组中1的位置+1 pos+1处-1
现在让我们先不考虑重复。经过如上处理,对于所有右边界等于pos+2的区间,树状数组中0~L的值即为三元组个数!
因为如果满足R等于pos+2 其实就是找所有出现过的l >= L的三元组,在遍历的过程中,每个满足要求的三元组pos+1处-1了,其实就是求0~L的区间和了
想想看~~
至于R 等于pos+2 由于对查询按照R排序了,所以在遍历的过程中对于每个pos都把查询遍历到右区间pos+2就好啦
这里没有去重,关于去重,我是琢磨了好久……做法就是哈希,哈希三元组。如果没出现过,跟上面一样,在线段树1处+1
如果出现过,需要在上次出现的位置+1处 累加上一个1
这样就可以避免重复统计了
做这道题真长记性……由于要哈希,排序必须对所有元素都进行比较。否则会出现重叠!这也是跟其内部实现相关。
代码如下:
#include <iostream> #include <cmath> #include <vector> #include <cstdlib> #include <cstdio> #include <cstring> #include <queue> #include <stack> #include <list> #include <algorithm> #include <map> #include <set> #define LL long long #define Pr pair<int,int> #define fread() freopen("in.in","r",stdin) #define fwrite() freopen("out.out","w",stdout) using namespace std; const int INF = 0x3f3f3f3f; const int msz = 10000; const int mod = 1e9+7; const double eps = 1e-8; int bit[233333]; int n; int Lowbit(int x) { return x&(-x); } int sum(int x) { int ans = 0; while(x) { ans += bit[x]; x -= Lowbit(x); } return ans; } void add(int x,int d) { while(x <= n) { bit[x] += d; x += Lowbit(x); } } struct Point { int l,r,id; bool operator <(const struct Point a)const { return r == a.r? l == a.l? id < a.id: l < a.l: r < a.r; } Point(int _l = 0,int _r = 0,int _id = 0):l(_l),r(_r),id(_id){}; }; Point pt[233333]; int num[233333]; int ans[233333]; int p[233333]; int main() { int t,m; scanf("%d",&t); while(t--) { scanf("%d",&n); for(int i = 1; i <= n; ++i) scanf("%d",&num[i]); scanf("%d",&m); for(int i = 0; i < m; ++i) { scanf("%d%d",&pt[i].l,&pt[i].r); pt[i].id = i; } memset(ans,0,sizeof(ans)); memset(bit,0,sizeof(bit)); sort(pt,pt+m); map <Point,int> mp; int j = 0; int tp = 1; for(int i = 1; i <= n-2; ++i) { if(num[i] <= num[i+1] && num[i+1] <= num[i+2]) { if(!mp[Point(num[i],num[i+1],num[i+2])]) { mp[Point(num[i],num[i+1],num[i+2])] = tp; p[tp++] = 0; } int x = mp[Point(num[i],num[i+1],num[i+2])]; add(p[x]+1,1); add(i+1,-1); p[x] = i; } for(; j < m && pt[j].r <= i+2; ++j) { if(pt[j].l+2 > pt[j].r) continue; ans[pt[j].id] = sum(pt[j].l); } } for(int i = 0; i < m; ++i) printf("%d\n",ans[i]); } return 0; }
以上是关于HDOJ 5654 xiaoxin and his watermelon candy(离线+树状数组)的主要内容,如果未能解决你的问题,请参考以下文章
HDU 5654 xiaoxin and his watermelon candy 离线树状数组
hdu 5654 xiaoxin and his watermelon candy 树状数组维护区间唯一元组
线段树+离线 hdu5654 xiaoxin and his watermelon candy
dp hdu5653 xiaoxin and his watermelon candy