ACM练级日志: CodeForces 414C 归并排序、逆序数和栈内存
来源:互联网 发布:微办公软件 编辑:程序博客网 时间:2024/06/13 12:06
时间一长居然连归并排序都忘了怎么写了…… 偏偏这玩意还不能用STL,必须手写…… 而且这道题又是递归又是取反又是求和,真心麻烦,费了我一个上午才弄出来……期间还遇上了各种各样的问题。
记录一下归并排序:开数组的时候没什么特殊情况就开在全局变量里,然后tmp数组也可以开在全局变量里,由于栈内存的限制,不要把局部变量开得很大,通常栈内存只有可怜的16MB,稍微奢侈一点就爆了……而且爆的特别坑爹,编译器会随便给你标记一行错了,还不让调试,如果不知道是这个问题的话,一辈子也不可能找到到底是哪错了。
这里稍微多说一句,上次做GCJ Round1A的B题时,已经想到了AC算法,就是大数据死活崩溃,估计就是栈内存的事。
递归层数不能过深其实跟这个是一样的道理,栈内存是他俩一块用的。
解决方法有这么几个:第一个是,当然,要是能开成全局的数组最好,这样就是内存总上限管你了;第二就是如果确认实际要处理的东西没那么多,可以用vector,就不会爆了;第三,可以手动扩大栈内存的量…… 这个是我查到的,还没有试验,不知管不管用
在头文件定义的区域加上一句:
#pragma comment(linker, "/STACK:1024000000,1024000000")
也不知道后面两个数什么意思,看着挺吓人的,不过他们都这么写……
然后说这道题,这道题是说一开始有一个长度为2^n的序列,然后不断地划分,前一半长度的数一组,后一半长度的数一组,然后下一层再划分,成为4组…… 直到化为每组只有一个数;接下来有q个操作,每个操作是把一层的所有组组内的数全部逆序,然后每做一次就会问你当前序列的逆序数是多少。
一开始确实想到了归并排序,毕竟这个结构几乎已经告诉你是归并排序了,问题就在于你不能真的去更新每一层的所有节点,如果他不断更新最后一层,那就变成n平方的了。由于一次是对一层操作,所以只需要给每层记录一个数就好。问题就在于这个数怎么定义,由于把每一层逆序时,所有的顺序对和逆序对都互换了,所以每一层只需要存储这一层的顺序对和逆序对即可。注意顺序对+逆序对不一定是对数的总数,因为两个相等的数既不是顺序对也不是逆序对。
然后另一个关键的问题就是谁更新谁。我一开始以为是向上更新,其实是不对的,应该是向下更新。假设现在有8个数,12345678,下设1234 5678 、 12 34 56 78, 1 2 3 4 5 6 7 8, 现在我要把第二层反向,那么可以理解成之后的全反向,变成4321 8765、 43 21 87 65, 4 3 2 1 8 7 6 5,这样才是正确的。不能只改一层,因为每一层逆序对/顺序对的信息其实是 (左边逆序对的数量) + (右边逆序对的数量) + 本层逆序对的数量,当你逆转一层的时候,后边的关系也变化了,而对于上面的节点来说,“本层逆序对的数量”是没有变的。(该从左边取还从左边取,右边同样)
然后贴一个归并排序求逆序数的模板
void merge(int s, int mid, int e, int level){ int i,j; int p=s; i=s; j=mid+1; while(i<=mid && j<=e) { if(a[i] <= a[j]) { tmp[p] = a[i]; i++; p++; } else { layer[level] += mid+1 - i;//只是求当前层的 tmp[p] = a[j]; j++; p++; } } while(i<=mid) { tmp[p] = a[i]; i++; p++; } while(j<=e) { tmp[p] = a[j]; p++; j++; } for(i=s;i<=e;i++) a[i] = tmp[i];} void merge_sort(int s, int e, int level){ if(e==s) return; int mid = (s+e) /2; merge_sort(s, mid, level-1); merge_sort(mid+1, e, level-1); merge(s, mid, e, level);}
反正就是每次merge的时候写tmp的一部分,然后把tmp的这一部分还给a就可以了。
求逆序数的时候,其实就是对于每一个左边的数,看一看右边的数里面有几个比他小的就行。这可以用二分搜索做,由于这道题既要求逆序对又要求顺序对,只靠归并是不行的,所以有的人这么做了,但是我自己写发现这样会超时…… 感觉是NlogNlogN的复杂度,有点悬,最后我是归并了两次,一次求顺序对,一次求逆序对,虽然笨拙了点,但是总算是过了……
- ACM练级日志: CodeForces 414C 归并排序、逆序数和栈内存
- 归并排序 逆序数 Codeforces 414 C
- 归并排序和逆序数
- Codeforces 414C Mashmokh and Reverse Operation 归并排序在线求交换序列后逆序数
- 归并排序,逆序数
- 归并排序 逆序数
- 归并排序+逆序数
- 归并排序 + 逆序数
- 归并排序和求逆序数对
- 归并排序和求逆序数
- acm 2299 java 利用归并排序求解逆序数
- ACM--归并排序&&树状数组--nyoj 117--求逆序数
- 归并排序/归并排序求逆序数
- codeforces 414C 归并排序
- 归并排序,求逆序数
- 归并排序求逆序数
- 逆序数--归并排序-nyoj117
- 归并排序求逆序数
- redhat切换用户前面是-bash-4.1$v
- 最短路
- Android学习Scroller(二)——ViewGroup调用scrollTo()
- POJ-3026 Borg Maze
- hdu-2504-分拆素数和
- ACM练级日志: CodeForces 414C 归并排序、逆序数和栈内存
- 0 \0 NULL 的区别
- Java集合类汇总记录-- apache.commons4(TreeList)
- Django 安装与新建项目
- 设计模式基本原则
- 黑马程序员-static关键字
- 变量声明和定义的区别
- 现在,我来了
- ACM练级日志:POJ 2886 约瑟夫环,线段树和反素数