[JZOJ5171]归并排序
来源:互联网 发布:发货找车用什么软件 编辑:程序博客网 时间:2024/06/10 22:43
题目大意
给定一个
答案对
题目分析
观察发现,出现bug的时候,较小的那个数在排完序之后一定在较大那个数的后一位置。因此我们将出现bug的情况看成较小的数变成较大的数
然后问题就可以变成
先考虑怎么做询问,我枚举这个数的取值,然后相当于我要求恰好有
然后这个个数怎么统计呢?其实就是一个二维数点的问题,因为要支持修改,因此我们可以考虑使用嵌套数据结构或者定期重构的KD-tree来解决,时间复杂度在
怎么优化时间呢?可以发现这题的点有特殊性质,就是它
代码实现
#include <algorithm>#include <iostream>#include <cstdio>#include <cctype>using namespace std;int read(){ int x=0,f=1; char ch=getchar(); while (!isdigit(ch)) f=ch=='-'?-1:f,ch=getchar(); while (isdigit(ch)) x=x*10+ch-'0',ch=getchar(); return x*f;}int buf[30];void write(int x){ if (x<0) putchar('-'),x=-x; for (;x;x/=10) buf[++buf[0]]=x%10; if (!buf[0]) buf[++buf[0]]=0; for (;buf[0];putchar('0'+buf[buf[0]--]));}const int itwo=500000004;const int P=1000000007;const int N=1<<18;int lowbit(int x){return x&-x;}int quick_power(int x,int y){ int ret=1; for (;y;y>>=1,x=1ll*x*x%P) if (y&1) ret=1ll*ret*x%P; return ret;}int fact[N],invf[N],POW[N],rg[N][2];int a[N];int n,q,d,lim;int C(int n,int m){return 1ll*fact[n]*invf[m]%P*invf[n-m]%P;}struct Fenwick_tree{ int v[N]; void modify(int x,int delta){for (;x<=lim;x+=lowbit(x)) v[x]+=delta;} int query(int x) { int ret=0; for (;x;x-=lowbit(x)) ret+=v[x]; return ret; }}t[2];void ADD(int x){t[0].modify(rg[x][0],1),t[1].modify(rg[x][1],1);}void DEL(int x){t[0].modify(rg[x][0],-1),t[1].modify(rg[x][1],-1);}void pre(){ d=quick_power(quick_power(2,n),P-2); fact[0]=1; for (int i=1;i<=n;++i) fact[i]=1ll*fact[i-1]*i%P; POW[0]=1; for (int i=1;i<=n;++i) POW[i]=1ll*POW[i-1]*itwo%P; invf[n]=quick_power(fact[n],P-2); for (int i=n;i>=1;--i) invf[i-1]=1ll*invf[i]*i%P; for (int i=0;i<n;++i) if (a[i]>a[i^1]) rg[i][0]=rg[i][1]=(a[i]<<1)-1; else rg[i][0]=(a[i]<<1)-1,rg[i][1]=a[i^1]<<1; for (int i=0;i<n;++i) ADD(i);}int calc(int x,int y){ int cnt=t[1].query(x-1),cnt_=t[0].query(x)-1; return cnt>y?0:1ll*C(cnt_-cnt,y-cnt)*POW[cnt_-cnt]%P;}int main(){ freopen("sort.in","r",stdin),freopen("sort.out","w",stdout); lim=(n=read())<<1; for (int i=0;i<n;++i) a[i]=read(); pre(); for (q=read();q--;) { int opt=read(),x=read()-1,y=read()-1; if (opt==1) { if (x==y) continue; DEL(x),DEL(x^1); if ((x|1)!=(y|1)) DEL(y),DEL(y^1); swap(a[x],a[y]); if (a[x]>a[x^1]) rg[x][0]=rg[x][1]=(a[x]<<1)-1,rg[x^1][0]=(a[x^1]<<1)-1,rg[x^1][1]=a[x]<<1; else rg[x][0]=(a[x]<<1)-1,rg[x][1]=a[x^1]<<1,rg[x^1][0]=rg[x^1][1]=(a[x^1]<<1)-1; if (x|1!=y|1) if (a[y]>a[y^1]) rg[y][0]=rg[y][1]=(a[y]<<1)-1,rg[y^1][0]=(a[y^1]<<1)-1,rg[y^1][1]=a[y]<<1; else rg[y][0]=(a[y]<<1)-1,rg[y][1]=a[y^1]<<1,rg[y^1][0]=rg[y^1][1]=(a[y^1]<<1)-1; ADD(x),ADD(x^1); if ((x|1)!=(y|1)) ADD(y),ADD(y^1); } else { int ans=1ll*(calc(rg[x][0],y)+calc(rg[x][1],y))*itwo%P; write(ans),putchar('\n'); } } fclose(stdin),fclose(stdout); return 0;}
阅读全文
0 0
- [JZOJ5171]归并排序
- 归并排序-归并排序
- 归并和归并排序
- 归并与归并排序
- 归并排序
- 归并排序
- 归并排序
- 归并排序
- 归并排序
- 归并排序
- 排序::归并
- 归并排序
- 归并排序
- 归并排序
- 归并排序
- 归并排序
- 归并排序
- 归并排序
- 【我的Android进阶之旅】推荐一款视频转换GIF图片格式的转换工具(Video to GIF)
- 记牌小程序开发
- java后台处理前端传的json串
- C++的数据类型--新手入门笔记
- 上传应用程序到App Store详解
- [JZOJ5171]归并排序
- android studio 创建项目一直停留在building gradle project info
- C语言 集合运算 并、交,相对补,对称差,判断两个集合是否相等,求集合幂集(改进幂集)
- Hadoop fs常用命令
- es6-Proxy
- Mybatis的二级缓存问题
- 百度地图POI+覆盖物+导航 实现
- HTML常用标签
- Android开发通过Xutil3获取数据并显示(list)