康托展开+线段树 Codeforces501D Misha and Permutations Summation
2016-01-16 19:24
429 查看
传送门:点击打开链接
题意:求两个排列的次序相加取模n!后,得到新的次序,然后输出这个次序对应的排列
思路:康托展开+逆展开+高精度。康托展开其实是个求逆序对的过程,逆展开实际上是一个找第k大的过程,都可以使用线段树来完成
因为数字非常大,所以肯定是要用高精度的,但是这里的高精度很特别,不是使用十进制的高精度,而是使用阶乘进制的高精度,这样就可以和康托展开和逆展开完美的结合起来了。
题意:求两个排列的次序相加取模n!后,得到新的次序,然后输出这个次序对应的排列
思路:康托展开+逆展开+高精度。康托展开其实是个求逆序对的过程,逆展开实际上是一个找第k大的过程,都可以使用线段树来完成
因为数字非常大,所以肯定是要用高精度的,但是这里的高精度很特别,不是使用十进制的高精度,而是使用阶乘进制的高精度,这样就可以和康托展开和逆展开完美的结合起来了。
#include<map> #include<set> #include<cmath> #include<ctime> #include<stack> #include<queue> #include<cstdio> #include<cctype> #include<string> #include<vector> #include<cstring> #include<iomanip> #include<iostream> #include<algorithm> #include<functional> #define fuck(x) cout<<"["<<x<<"]" #define FIN freopen("input.txt","r",stdin) #define FOUT freopen("output.txt","w+",stdout) using namespace std; typedef long long LL; typedef pair<int, int>PII; const int MX = 2e5 + 5; const int mod = 1e9 + 7; const int INF = 0x3f3f3f3f; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 int S[MX << 2], A[MX], B[MX], n; void push_up(int rt) { S[rt] = S[rt << 1] + S[rt << 1 | 1]; } void add(int x, int l, int r, int rt) { if(l == r) { S[rt]++; return; } int m = (l + r) >> 1; if(x <= m) add(x, lson); else add(x, rson); push_up(rt); } int sum(int L, int R, int l, int r, int rt) { if(L <= l && r <= R) return S[rt]; int m = (l + r) >> 1, ret = 0; if(L <= m) ret += sum(L, R, lson); if(R > m) ret += sum(L, R, rson); return ret; } void build(int l, int r, int rt) { if(l == r) { S[rt] = 1; return; } int m = (l + r) >> 1; build(lson); build(rson); push_up(rt); } int query(int x, int l, int r, int rt) { if(l == r) { S[rt]--; return l; } int m = (l + r) >> 1, ret; if(x <= S[rt << 1]) ret = query(x, lson); else ret = query(x - S[rt << 1], rson); push_up(rt); return ret; } void Contor(int A[]) { memset(S, 0, sizeof(S)); for(int i = 0; i < n; i++) { int t; scanf("%d", &t); t++; A[n - i - 1] = t - sum(1, t, 1, n, 1) - 1; add(t, 1, n, 1); } } void solve() { build(1, n, 1); A[0] = 0; for(int i = n - 1; i >= 0; i--) { int x = query(A[i] + 1, 1, n, 1) - 1; printf("%d%c", x, i == 0 ? '\n' : ' '); } } int main() { //FIN; while(~scanf("%d", &n)) { Contor(A); Contor(B); for(int i = 1, t = 0; i < n; i++) { A[i] += B[i] + t; t = A[i] / (i + 1); A[i] -= t * (i + 1); } solve(); } return 0; }
相关文章推荐
- [乡土民间故事_徐苟三传奇]第四三回_砍棉梗姚财主认输
- arcmap坐标点生成线和面(更正版)
- linux安装mysql
- windows下定期清理超过一定时间的文件
- 未来的几个大的方向
- UESTC ZhangYu Speech 1269 (模拟&技巧转换)
- 3.3 启发式搜索
- 开发手机应用(微信公众号)
- linux c语言使用sim900打电话发短信
- [乡土民间故事_徐苟三传奇]第四二回_见洋广争啃西瓜皮
- Caffe学习系列(21):caffe图形化操作工具digits的安装与运行
- Android开发主页框架搭建
- iOS(五)基于XMPP协议的聊天App:二
- UESTC 1269-ZhangYu Speech
- [乡土民间故事_徐苟三传奇]第四一回_放牛娃巧娶富家女
- ViewController的生命周期分析和使用
- I NEED A OFFER!
- 一张图,理解JAVA体系结构、运行机制、JVN运行机制、Java平台(初学)
- Github实践
- java动态代理demo