数列还原 2017网易校招(树状数组预处理+全排列)
2018-01-04 22:43
344 查看
时间限制:1秒 空间限制:32768K 热度指数:5122
算法知识视频讲解
牛牛的作业薄上有一个长度为 n 的排列 A,这个排列包含了从1到n的n个数,但是因为一些原因,其中有一些位置(不超过 10 个)看不清了,但是牛牛记得这个数列顺序对的数量是 k,顺序对是指满足 i < j 且 A[i] < A[j] 的对数,请帮助牛牛计算出,符合这个要求的合法排列的数目。
示例1
算法知识视频讲解
题目描述
牛牛的作业薄上有一个长度为 n 的排列 A,这个排列包含了从1到n的n个数,但是因为一些原因,其中有一些位置(不超过 10 个)看不清了,但是牛牛记得这个数列顺序对的数量是 k,顺序对是指满足 i < j 且 A[i] < A[j] 的对数,请帮助牛牛计算出,符合这个要求的合法排列的数目。
输入描述:
每个输入包含一个测试用例。每个测试用例的第一行包含两个整数 n 和 k(1 <= n <= 100, 0 <= k <= 1000000000),接下来的 1 行,包含 n 个数字表示排列 A,其中等于0的项表示看不清的位置(不超过 10 个)。
输出描述:
输出一行表示合法的排列数目。
示例1
输入
5 5 4 0 0 2 0
输出
2
#include <bits/stdc++.h> using namespace std; set<int>st; int a[111], c[111], cnt[111], b[11][111], tot, num[11], n, k, have, cc[111]; inline int lowbit(int x){ return x & (-x); } void add(int c[], int x, int v){ while(x <= n){ c[x] += v; x += lowbit(x); } } int query(int c[], int x){ int ans = 0; while(x){ ans += c[x]; x -= lowbit(x); } return ans; } bool check(){ int all = have; for(int i = 1; i <= tot; ++i){ all += b[i][num[i]]; } memset(cc, 0, sizeof(cc)); for(int i = 1; i <= tot; ++i){ all += query(cc, num[i]); add(cc, num[i], 1); } if(all == k){ return true; } else{ return false; } } int main(){ cin >> n >> k; memset(c, 0, sizeof(c)); have = 0; tot = 0; for(int i = 1; i <= n; ++i){ scanf("%d", &a[i]); if(a[i] == 0){ tot++; for(int j = 1; j <= n; ++j){ b[tot][j] = query(c, j); } continue; } cnt[a[i]] = 1; have += query(c, a[i]); add(c, a[i], 1); } memset(c, 0, sizeof(c)); int x = 0; for(int i = n; i >= 1; --i){ if(a[i] != 0){ add(c, a[i], 1); } else{ for(int j = 1; j <= n; ++j){ b[tot][j] += n - i - x - query(c, j); } x++; tot--; } } for(int i = 1; i <= n; ++i){ if(cnt[i] == 0){ st.insert(i); } } tot = 0; int ans = 0; set<int>::iterator it; for(it = st.begin(); it != st.end(); ++it){ num[++tot] = *it; } sort(num + 1, num + 1 + tot); do{ if(check()){ ans++; } }while(next_permutation(num + 1, num + 1 + tot)); cout << ans << endl; } /* 题意: 一个1到n的排列,有不超过10个数看不清了,现在让你还原这个数列,使得正序列对数为k。 思路: 这题的数据是真的弱。。我是n!log(10), 4ms过的。 先n^2log(n)预处理一下每个为0的位置填1到n的时候分别会对清楚的位置增加多少个正序列对, 然后nlog(n)求一下清楚的部分的正序列对数。 然后全排列枚举,这样对于新填的数对于清楚的数的影响可以O(1)求,然后对于新填的数的序列 求一下正序列数,加一下判断一下即可。 */
相关文章推荐
- D-query SPOJ - DQUERY (树状数组离线预处理||主席树)
- Apple Tree(需要预处理的树状数组)
- [区间GCD预处理 树状数组 离线] HDU 5869 Different GCD Subarray Query
- [置顶] HDU 4777 Rabbit Kingdom(离线树状数组 预处理)
- POJ 3110 Jenny's First Exam (二分 + 树状数组 + 贪心 + 预处理年份)
- hdu-5869 Different GCD Subarray Query gcd预处理 + 树状数组 + 离线
- 【BestCoder Round 65C】【树状数组 动态查找第k大 O(nlogn)】ZYB's Premutation 告诉你前i个数中的逆序对数让你还原全排列
- 第四讲 递归原理--数组的全排列(递归+交换)
- HDU 3584 三维树状数组
- poj 2229 Ultra-QuickSort(树状数组求逆序数)
- poj——2299树状数组求逆序数
- 离散化加树状数组求逆序数。
- 【分块】【树状数组】bzoj3787 Gty的文艺妹子序列
- POJ 2299 Ultra-QuickSort(树状数组+离散化)
- 树状数组--Ultra-QuickSort
- 树状数组简单题----杭电1541
- [树状数组][离散化]Ultra-QuickSort
- [dfs序 树状数组] BZOJ 4034 [HAOI2015]T2
- [DP] [2D2D优化] [二维树状数组] [SCOI2014] 方伯伯的玉米田
- FZU2236 第十四个目标 (树状数组)