Codeforces Round #285 (Div.1 B & Div.2 D) Misha and Permutations Summation --二分+树状数组
2015-01-12 20:28
567 查看
题意:给出两个排列,求出每个排列在全排列的排行,相加,模上n!(全排列个数)得出一个数k,求出排行为k的排列。
解法:首先要得出定位方法,即知道某个排列是第几个排列。比如 (0, 1, 2), (0, 2, 1), (1, 0, 2), (1, 2, 0), (2, 0, 1), (2, 1, 0).
拿排列(1,2,0)来说,首位是1,前面有cnt=1个小于1的没被用过的数(0),所以它的排行要加上(cnt=1)*2!,第二位为2,因为1已经放了,所以小于2的只有0了,即cnt=1个,所以,排行又要加上(cnt=1)*1!,所以排行为3.
推出一般性结论:
View Code
比赛中写的代码,没有最简化,有很多冗余和多此一举的地方。
解法:首先要得出定位方法,即知道某个排列是第几个排列。比如 (0, 1, 2), (0, 2, 1), (1, 0, 2), (1, 2, 0), (2, 0, 1), (2, 1, 0).
拿排列(1,2,0)来说,首位是1,前面有cnt=1个小于1的没被用过的数(0),所以它的排行要加上(cnt=1)*2!,第二位为2,因为1已经放了,所以小于2的只有0了,即cnt=1个,所以,排行又要加上(cnt=1)*1!,所以排行为3.
推出一般性结论:
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <algorithm> #include <string> #include <vector> #include <queue> using namespace std; #define N 200107 int p1 ,p2 ,p3 ,c ; int n; int lowbit(int x) { return x&-x; } void modify(int x,int val) { while(x <= n+10) { c[x] += val; x += lowbit(x); } } int getsum(int x) { int res = 0; while(x > 0) { res += c[x]; x -= lowbit(x); } return res; } int main() { int i,j,x; while(scanf("%d",&n)!=EOF) { memset(c,0,sizeof(c)); for(i=1;i<=n;i++) modify(i,1); for(i=1;i<=n;i++) { scanf("%d",&x); x++; p1[i] = getsum(x-1); modify(x,-1); } memset(c,0,sizeof(c)); for(i=1;i<=n;i++) modify(i,1); for(i=1;i<=n;i++) { scanf("%d",&x); x++; p2[i] = getsum(x-1); modify(x,-1); } memset(p3,0,sizeof(p3)); for(i=n;i>=1;i--) { p3[i] += p1[i]+p2[i]; if(p3[i] >= (n-i+1)) { p3[i] = p3[i]-(n-i+1); if(i != 1) p3[i-1]++; } } memset(c,0,sizeof(c)); for(i=1;i<=n;i++) modify(i,1); // for(i=1;i<=n;i++) // cout<<p3[i]<<" "; // cout<<endl; for(i=1;i<=n;i++) { int low = 1, high = n; while(low <= high) { int mid = (low+high)/2; if(getsum(mid-1) > p3[i]) high = mid-1; else if(getsum(mid-1) == p3[i] && getsum(mid)-getsum(mid-1) == 1) high = mid-1; else if(getsum(mid-1) == p3[i] && getsum(mid)-getsum(mid-1) < 1) low = mid+1; else if(getsum(mid-1) < p3[i]) low = mid+1; } modify(low,-1); printf("%d ",low-1); } puts(""); } return 0; }
View Code
比赛中写的代码,没有最简化,有很多冗余和多此一举的地方。
相关文章推荐
- Codeforces Round #285 (Div. 1)B. Misha and Permutations Summation(数学+数据结构打脸)
- Codeforces Round #285 (Div. 2) D. Misha and Permutations Summation 康托展开 树状数组+二分
- Codeforces Round #365 (Div. 2) Mishka and Interesting sum 树状数组
- codeforces round 285 div285 Misha and Forest
- B. Misha and Changing Handles(Codeforces Round 285(div2))
- Codeforces Round #285 (Div. 2) ---B. Misha and Changing Handles
- Codeforces Round #285 (Div. 2) C. Misha and Forest
- Codeforces Round 459 D. Pashmak and Parmida's problem 树状数组求逆序数 变形
- Codeforces Round #365 (Div. 2) D.Mishka and Interesting sum (树状数组维护异或值) ★ ★
- 【Codeforces Round 365 (Div 2)D】【离线询问 树状数组 前驱思想】Mishka and Interesting sum 区间内出现次数偶数的数的异或和
- Codeforces Round #285 (Div. 2) C. Misha and Forest
- Codeforces Round #404 (Div. 2) E. Anton and Permutation(树状数组套主席树 求出指定数的排名)
- Codeforces Round #285 (Div. 2) C. Misha and Forest
- Codeforces Round #285 (Div. 2) C. Misha and Forest
- Codeforces Round #318 [RussianCodeCup Thanks-Round] (Div. 2)——A二分——Bear and Elections
- Educational Codeforces Round 3 D.Gadgets for dollars and pounds(贪心&&二分)
- Codeforces Round #261 (Div. 2) D. Pashmak and Parmida's problem
- Codeforces Round #299 (Div. 1) A. Tavas and Karafs(二分)
- Codeforces Round #330 (Div. 2)D. Max and Bike 二分 物理
- Codeforces Round #248 (Div. 2) B称号 【数据结构:树状数组】