数据结构(主席树):HDU 5654 xiaoxin and his watermelon candy

Problem Description

  During his six grade summer vacation, xiaoxin got lots of watermelon candies from his leader when he did his internship at Tencent. Each watermelon candy has it‘s sweetness which denoted by an integer number.

  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 (ai,aj,ak) then:
    1. j=i+1,k=j+1
    2.  ai≤aj≤ak

  Your task is to calculate how many different ways xiaoxin can choose a triplet in range [L, R]?
two triplets (a0,a1,a2) and (b0,b1,b2) are thought as different if and only if:
a0≠b0 or a1≠b1 or a2≠b2


Input

  This problem has multi test cases. First line contains a single integer T(T≤10) which represents the number of test cases.

  For each test case, the first line contains a single integer n(1≤n≤200,000)which represents number of watermelon candies and the following line contains n integer numbers which are given in the order same with xiaoxin arranged them from left to right.
The third line is an integer Q(1≤200,000) which is the number of queries. In the following Q lines, each line contains two space seperated integers l,r(1≤l≤r≤n) which represents the range [l, r].


Output

  For each query, print an integer which represents the number of ways xiaoxin can choose a triplet.


Sample Input

1 5 1 2 3 4 5 3 1 3 1 4 1 5


Sample Output

1 2 3

  这道题额,对于每个点建一棵线段树,表示以它为左端点的所有区间……口胡不清。
 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <algorithm>
 5 using namespace std;
 6 const int maxn=200010;
 7 int a[maxn],Hash[maxn],ok[maxn];
 8 int pre[maxn],nxt[maxn],head[maxn],fa[maxn],son[maxn];
 9 int sum[maxn*30],ch[maxn*30][2],rt[maxn],cnt;
10 void Insert(int pre,int &rt,int l,int r,int g,int d){
11     rt=++cnt;
12     ch[rt][0]=ch[pre][0];
13     ch[rt][1]=ch[pre][1];
14     sum[rt]=sum[pre]+d;
15     if(l==r)return;
16     int mid=(l+r)>>1;
17     if(mid>=g)Insert(ch[pre][0],ch[rt][0],l,mid,g,d);
18     else Insert(ch[pre][1],ch[rt][1],mid+1,r,g,d);
19 }
20
21 int Query(int rt,int l,int r,int a,int b){
22     if(l>=a&&r<=b)return sum[rt];
23     int mid=(l+r)>>1,ret=0;
24     if(mid>=a)ret=Query(ch[rt][0],l,mid,a,b);
25     if(mid<b)ret+=Query(ch[rt][1],mid+1,r,a,b);
26     return ret;
27 }
28 void Init(){
29     memset(rt,0,sizeof(rt));
30     memset(head,0,sizeof(head));
31     memset(pre,0,sizeof(pre));
32     memset(son,0,sizeof(son));
33     memset(nxt,0,sizeof(nxt));
34     memset(fa,0,sizeof(fa));
35     memset(sum,0,sizeof(sum));
36     memset(ok,0,sizeof(ok));cnt=0;
37 }
38 int main(){
39     int T,Q,n,l,r;a[0]=-1;
40     scanf("%d",&T);
41     while(T--){
42         Init();
43         scanf("%d",&n);
44         for(int i=1;i<=n;i++)
45             scanf("%d",&a[i]);
46         for(int i=1;i<=n;i++)
47             Hash[i]=a[i];
48         sort(Hash+1,Hash+n+1);
49         for(int i=1;i<=n;i++)
50             a[i]=lower_bound(Hash+1,Hash+n+1,a[i])-Hash;
51         for(int i=2;i<n;i++)
52             if(a[i-1]<=a[i]&&a[i]<=a[i+1])
53                 ok[i]=1;
54         for(int i=1;i<=n;i++){
55             pre[i]=head[a[i]];
56             nxt[pre[i]]=i;
57             head[a[i]]=i;
58         }
59         for(int i=2;i<n;i++)
60             if(ok[i]){
61                 int j=pre[i];
62                 while(j&&(a[j-1]!=a[i-1]||a[j+1]!=a[i+1])){j=pre[j];}
63                 fa[i]=j;son[j]=i;
64             }
65         for(int i=2;i<n;i++){
66             if(!fa[i]&&ok[i])
67                 Insert(rt[1],rt[1],1,n,i,1);
68         }
69
70         for(int i=2;i<n;i++){
71             if(!ok[i]){
72                 rt[i]=rt[i-1];
73                 continue;
74             }
75             Insert(rt[i-1],rt[i],1,n,i,-1);
76             if(son[i])Insert(rt[i],rt[i],1,n,son[i],1);
77         }
78         scanf("%d",&Q);
79         while(Q--){
80             scanf("%d%d",&l,&r);
81             printf("%d\n",r-1>=l?Query(rt[l],1,n,1,r-1):0);
82         }
83     }
84     return 0;
85 }   
时间: 2024-08-09 23:56:04

数据结构(主席树):HDU 5654 xiaoxin and his watermelon candy的相关文章

HDU 5654 xiaoxin and his watermelon candy 离线树状数组

xiaoxin and his watermelon candy Problem Description During his six grade summer vacation, xiaoxin got lots of watermelon candies from his leader when he did his internship at Tencent. Each watermelon candy has it's sweetness which denoted by an inte

hdu 5654 xiaoxin and his watermelon candy 树状数组维护区间唯一元组

题目链接 题意:序列长度为n(1<= n <= 200,000)的序列,有Q(<=200,000)次区间查询,问区间[l,r]中有多少个不同的连续递增的三元组. 思路:连续三元组->递推O(n)将第一次出现该三元组的下标记录到树状数组中,并且用一个Next[]来表示递推关系,即同一个三元组下一次出现的位置是Next[x];这很关键,在之后按照左边界处理时(有点像莫队算法),一直递推在l+1左侧重复出现的三元组,为了把该三元组推到出现在[l,r]或者[r+1,..]中,这样不重不漏.

线段树+离线 hdu5654 xiaoxin and his watermelon candy

传送门:点击打开链接 题意:一个三元组假设满足j=i+1,k=j+1,ai<=aj<=ak,那么就好的.如今告诉你序列.然后Q次询问.每次询问一个区间[l,r],问区间里有多少个三元组满足要求 思路:刚開始看错题目了,原来三元组是连续3个,这作为bc最后一题也太水了把. . . 先一遍预处理.把连续3个满足条件的找出来,放到还有一个数组里排序去重,用这个数组来给三元组哈希.再扫一遍给三元组在之前那个排序好的数组里二分一下得到下标,大概就是哈希一下,用一个数字来表示. 之后的查询.事实上就是.在

数据结构(主席树):COGS 2213. K个串

2213. K个串 ★★★★   输入文件:bzoj_4504.in   输出文件:bzoj_4504.out   简单对比时间限制:20 s   内存限制:512 MB [题目描述] 兔子们在玩k个串的游戏.首先,它们拿出了一个长度为n的数字序列,选出其中的一 个连续子串,然后统计其子串中所有数字之和(注意这里重复出现的数字只被统计一次). 兔子们想知道,在这个数字序列所有连续的子串中,按照以上方式统计其所有数字之和,第 k大的和是多少. [输入格式] 第一行,两个整数n和k,分别表示长度为n

【HDOJ 5654】 xiaoxin and his watermelon candy(离线+树状数组)

pid=5654">[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 Problem Des

主席树 hdu 4348

题意:有一个由n个数组成的序列,有4中操作: 1.C l r d [l,r]这段区间都加上d 2.Q l r 询问[l,r]这段区间的和 3.H l r t 询问之前t时间[l,r]的区间和 4.B t 回到t时间,且下一秒的时间从t开始 按时间建立主席树,主席树上的每一棵线段树维护[1,n]这段序列的信息,这里成段更新的时候要注意,以往写线段树的时候,都是把lazy标记向下传,但是写主席树的时候每一次下传,那么新的节点数就会非常多,会爆内存,所以我们不把lazy操作下传,只是在询问的时候,最后

数据结构 - 主席树

查询 $[l,r]$ 区间第 $k$ 小的值. #include <algorithm> #include <cstdio> #include <cstring> using namespace std; const int maxn = 1e5; //数据范围 int tot, n, m; int sum[(maxn << 5) + 10], rt[maxn + 10], ls[(maxn << 5) + 10], rs[(maxn <&

dp hdu5653 xiaoxin and his watermelon candy

传送门:点击打开链接 题意:有n个箱子排成一排,有m个炸弹.位置告诉你.如今炸弹的左边伤害和右边伤害能够自己控制,要求 每一个炸弹炸的箱子数的累乘,输出答案取log2并乘以1e6 思路:直接2for xjb搞即可了.大概就是某个区间里刚好仅仅有一个炸弹时,就是满足的,然后就从前面往后面更新一下 #include <map> #include <set> #include <cmath> #include <ctime> #include <stack&

关于树状数组套主席树的一些博客

哇仿佛磕了几百年啊; 废话不多说,以下是帮助很大的一些blog: ZOJ 2112 Dynamic Rankings (动态第k大,树状数组套主席树) 主席树全纪录(这个很好) 主席树乱讲(没啥关系,不过有些题目可以刷??) 随笔分类 - 数据结构---主席树(同上) 原文地址:https://www.cnblogs.com/wwtt/p/10099695.html