【HDU5654 BestCoder Round 77 (div1) D】【前驱位置思想 排序 树状数组】xiaoxin and his watermelon candy 区间内多少个不同连续单升三元
2016-03-27 22:51
549 查看
xiaoxin and his watermelon candy
Accepts: 15Submissions: 172
Time Limit: 4000/4000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
问题描述
六年级的暑假,在腾讯实习的xiaoxin巨从leader那得到了很多西瓜糖。每个西瓜糖都有一个属性代表它的甜度值,用一个正整数表示。 xiaoxin从小就特别会玩,他先把所有糖果排成一条直线,每次从一个区间内选出三个连续的且甜度值不减的西瓜糖来吃,即: 如果他选择了三元组 (a_i, a_j, a_k)(ai,aj,ak) 那么: 1. j = i + 1, k = j + 1j=i+1,k=j+1 2. a_i \leq a_j \leq a_kai≤aj≤ak 好奇的xiaoxin想知道每次吃糖果,他有多少种吃法? 我们认为两个三元组 (a_0, a_1, a_2), (b_0, b_1, b_2)(a0,a1,a2),(b0,b1,b2) 是不同的,当且仅当: a_0 \neq b_0a0≠b0 or a_1 \neq b_1a1≠b1 or a_2 \neq b_2a2≠b2.
输入描述
多组测试数据, 第一行为一个整数(T \leq 10T≤10)表示测试数据组数。 对于每组测试数据,第一行是一个整数 n(1 \leq n \leq 200,000)n(1≤n≤200,000) 表示西瓜糖的个数。接下来 nn个数表示每个西瓜糖的甜度值(0 \leq a_i \leq 1000,000,0000≤ai≤1000,000,000)。接下来有 Q(1 \leq 200,000)Q(1≤200,000) 行代表询问的次数,每个询问用两个整数 l, r(1\leq l \leq r \leq n)l,r(1≤l≤r≤n) 表示。
输出描述
对于每次询问,输出一个数,表示这次xiaoxin的吃法的数目。
输入样例
1 5 1 2 3 4 5 3 1 3 1 4 1 5
输出样例
1 2 3
#include<stdio.h> #include<iostream> #include<string.h> #include<string> #include<ctype.h> #include<math.h> #include<set> #include<map> #include<vector> #include<queue> #include<bitset> #include<algorithm> #include<time.h> using namespace std; void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); } #define MS(x,y) memset(x,y,sizeof(x)) #define MC(x,y) memcpy(x,y,sizeof(x)) #define MP(x,y) make_pair(x,y) #define ls o<<1 #define rs o<<1|1 typedef long long LL; typedef unsigned long long UL; typedef unsigned int UI; template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b>a)a = b; } template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b<a)a = b; } const int N = 2e5 + 10, M = 0, Z = 1e9 + 7, ms63 = 0x3f3f3f3f; int casenum, casei; int n, m; int c ; //用于记录原数的数组 int b ; //树状数组,我们利用其来统计在某个范围内有多少个数字的前驱<l int nxt ; //nxt[i]表示与c[i]权值相同的下一个数的位置 int l , r , o ; //用于处理询问的数组 int ans ; //用于输出答案的数组 map< pair<int, pair<int, int> >, int>mop; map< pair<int, pair<int, int> >, int>::iterator it; bool cmp(int x, int y) { return l[x] < l[y]; } int check(int x) { int ret = 0; for (; x; x -= x&-x)ret += b[x]; return ret; } void add(int x, int val) { for (; x <= n; x += x&-x)b[x] += val; } int main() { scanf("%d", &casenum); for (casei = 1; casei <= casenum; ++casei) { mop.clear(); scanf("%d", &n); for (int i = 1; i <= n; ++i)b[i] = nxt[i] = 0; for (int i = 1; i <= n; ++i)scanf("%d", &c[i]); for (int i = 3; i <= n; ++i) { if (i >= 3 && c[i - 2] <= c[i - 1] && c[i - 1] <= c[i]) { int x = mop[MP(c[i - 2], MP(c[i - 1], c[i]))]; if (x == 0)add(i, 1); else nxt[x] = i; mop[MP(c[i - 2], MP(c[i - 1], c[i]))] = i; } } scanf("%d", &m); for (int i = 1; i <= m; ++i)scanf("%d%d", &l[i], &r[i]), o[i] = i; sort(o + 1, o + m + 1, cmp); int p = 1; for (int i = 1; i <= m; ++i) { int lft = l[o[i]]; int rgt = r[o[i]]; while (p <= lft + 1) { if(nxt[p])add(nxt[p], 1); ++p; } if (rgt - lft >= 2)ans[o[i]] = check(rgt) - check(lft + 1); else ans[o[i]] = 0; } for (int i = 1; i <= m; ++i)printf("%d\n", ans[i]); } return 0; } /* 【trick&&吐槽】 1,注意,我们一定要注意我们对于一个[l,r]的询问区间,其所对应的真实区间其实是[l+2,r] 2,边界问题把握好,比如—— if (rgt - lft >= 2)ans[o[i]] = check(rgt) - check(lft + 1); else ans[o[i]] = 0; 这第二句不能忽视 3,复杂度固然重要,但是代码复杂度也非常重要,否则实现不了程序再快又有什么用 【题意】 问你一个区间中有多少个本质不同的连续不下降三元组 即(ai,aj,ak)满足i+1=j,j+1=k且a[i]<=a[j]<=a[k] 【类型】 树状数组 排序 【分析】 我们要统计的是区间范围[l,r]内有多少个三元组的pre小于l。 为了实现这个功能,一个好的做法是,在数据结构中,只维护所有pre<l的数。 显然,随着查询区间左界l的增大,pre<l的数是增多的。 于是,我们队所有的查询按照左界做排序。 我们之前会把pre<l的所有数都放进位置恰好其下标所对应的数据结构(如树状数组)中。 那我们查询的时候,只要查询[lft+2,rgt]期间有多少个数即可 【时间复杂度&&优化】 O(nlogn) */
相关文章推荐
- 【HDU5565 BestCoder Round 62 (div1)C】【STL or 二分答案 or 计数排序】Clarke and baton n个人减肥m次求最后异或值
- 【HDU5564 BestCoder Round 62 (div1)B】【DP转矩阵快速幂】Clarke and digits 长度在[l,r]范围内7倍数数个数要求相邻两位不为K
- 【HDU5544 2015CCPC 南阳国赛E】【树上dfs找本质不同环 高斯消元 时间戳优化】Ba Gua Zhen 连通图上最大异或环
- 【HDU5222 2015赛码冠军杯I】【并查集找双连通 + tarjan求强连通】Exploration 双向边只能走一边是否图上存在环
- 【HDU5188 BestCoder Round 33C】【贪心排序+DP】zhx and contest 考试不被怀疑作弊条件下达到至少m分的最少时间
- 【HDU4560 2013西山居复赛D】【二分答案+网络流拆点】我是歌手 安排演唱会_每人歌不同_每场歌不同_人歌匹配一次
- 【HDU5411 2015 Multi-University Training Contest 10F】【矩阵快速幂 加一行构造法】CRB and Puzzle 矩阵的1次方到n次方的数值和
- 【HDU5570 BestCoder Round 63 (div1)C】【期望DP 公式化简】balls n种求m种颜色,同颜色球数为x贡献为x方 求期望
- 【HDU5569 BestCoder Round 63 (div1)B】【DP】matrix 向右走向下走最大乘积和
- 【HDU5568 BestCoder Round 63 (div1)A】【DP java高精度】sequence2 长度恰好为m的LIS数
- 【Codeforces Round 333 (Div 2)E】【期望DP概率做法 树状数组转前缀和】Kleofáš and the n-thlon n场比赛m个人获得总名次的期望
- 【Codeforces Testing Round 12C】【DP 树状数组优化】Subsequences n个不同数,长度为m的LIS数
- 【HDU5579 2015上海赛区G】【超级大讨论】Game of Arrays a[]+b[]+c[]有些位置可以减一,状态是否可能达成
- 【HDU5583 2015上海赛区L】【找规律 正难则反】LCM Walk 目标状态(x,y)哪些点走公倍数能走到它
- 【HDU5573 2015上海赛区B】【构造 二进制思想】Binary Tree 二叉树上走m层加减数使得最后权值恰为n
- 【HDU5583 2015上海赛区K】【暴力合并】Kingdom of Black and White 连续01串权值贡献为len^2最多改变一次最大权值
- 【HDU5578 2015上海赛区F】【水题】Friendship of Frog 最近的两个相同字符的距离是多少
- 【HDU5586 BestCoder Round 64 (div1)A】【贪心 最大连续子串】Sum 区间函数值变换使得数列权值和最大
- 【HDU5587 BestCoder Round 64 (div1)B】【迭代 前缀和思想】Array 前m个数的二进制中共有多少个1
- 【HDU6197 2017 ACM ICPC Asia Regional Shenyang Online D】【LIS 最长不下降序列】array array array 数列删除恰好K个数,使得恰好