【cqoi2011】动态逆序对
来源:互联网 发布:win10缺少—个网络协议 编辑:程序博客网 时间:2024/06/03 09:13
时间限制:1秒 内存限制:64M
【问题描述】
对于序列A[i],它的逆序对数定义为满足:i < j,且A[i] > A[j]的数对(i,j)的个数。
给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数。
【输入格式】
输入第一行包含两个整数n和m,即初始元素的个数和删除的元素个数。以下n行每行包含一个1到n之间的正整数,即初始排列。以下m行每行一个正整数,依次为每次删除的元素。
【输出格式】
输出包含m行,依次为删除每个元素之前,逆序对的个数。
【输入样例】
5 4
1
5
3
4
2
5
1
4
2
【输出样例】
5
2
2
1
【数据范围】
编号 1-2 3-4 5-6 7-8 9-10
n <=1000 <=30000 <=50000 <=60000 <=100000
m <=100 <=10000 <=20000 <=40000 <=50000
【来源】
(1,5,3,4,2) -> (1,3,4,2) -> (3,4,2) -> (3,2) -> (3)。
今天晚上一直在做这道题,做了几种方法出来,但时间复杂度各不相同,准确的说只是常数不同,但就是这个常数有2种方法看起来可以却要被卡住1~2个点。
第一种方法:树套树,常数极高,可能是因为我用的线段树套平衡树,线段树的常数大了点。
第二种:分块+排序,普通的分块方法,就按照要求,分成几块,然后块内排序。删除就找前面比他大的和后面比他小的就好。会卡常数一个点。
第三种:分块+bit,也是分块,而且这种方法也要优化才能过,用bit记录块内的值,bit[i][j]前i个块一共有多少个在j所属的范围内。这个前缀和的思想可以省很多时间。
第四种:CDQ分治,也要优化,优化了特别快,没有优化特别慢,最可怕的是不容易看出来优化在哪里。
第五种:持续化线段树:思想和分块加bit的优化版差不多。
这里我提供一下CDQ分治的代码(因为难想),一个优化了的,一个没优化的,其他代码就不给了,请读者自己好好写,都不难但是请主要细节。
#include<cstdlib>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;typedef long long ll;const int maxn=1000005;struct shu{ int x,id,y; ll ans; friend bool operator <(shu a,shu b) { return a.y<b.y; }}a[maxn],c[maxn];int n,m,bit[maxn],b[maxn];ll lowbit(ll x){ return x&(-x);}void in(ll x){ for(;x<=n;x+=lowbit(x)) bit[x]++;}void out(ll x){ for(;x<=n;x+=lowbit(x)) bit[x]=0;}ll find(ll x){ ll t=0; for(;x>=1;x-=lowbit(x)) t+=bit[x]; return t;}bool cmp(shu a,shu b){ return a.id<b.id;}/*这是没优化的void work(int l,int r){ if(l==r) return; int m=(l+r)>>1; work(l,m); work(m+1,r); sort(a+l,a+m+1); sort(a+m+1,a+r+1); int j=l; for(int i=m+1;i<=r;i++) { while(j<=m&&a[j].y<a[i].y) { in(n+1-a[j].x); j++; } a[i].ans+=find(n-a[i].x); } while(j>=l) { out(n+1-a[j].x); j--; } j=m; for(int i=r;i>m;i--) { while(j>=l&&a[j].y>a[i].y) { in(a[j].x); j--; } a[i].ans+=find(a[i].x-1); } while(j<=m) { out(a[j].x); j++; }}*///这是优化了的,请自行对比。(可以复制下来试试速度,保证长见识)void work(int l,int r){ if(l==r) return; int m=(l+r)>>1; work(l,m); work(m+1,r); sort(a+l,a+r+1); int j=l; for(int i=l;i<=r;i++) { if(a[i].id<=m) in(n+1-a[i].x); else a[i].ans+=find(n-a[i].x); } for(int i=l;i<=r;i++) if(a[i].id<=m) out(n+1-a[i].x); j=m; for(int i=r;i>=l;i--) { if(a[i].id<=m) in(a[i].x); else a[i].ans+=find(a[i].x-1); } for(int i=l;i<=r;i++) if(a[i].id<=m) out(a[i].x);}int read(){ int x=0; bool ok=0; char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-') ch=getchar(); while((ch>='0'&&ch<='9')||ch=='-') { if(ch=='-') ok=1; else x=x*10+ch-'0'; ch=getchar(); } return ok?-x:x;}char ch[50];void out2(ll x){ int len=0; if(!x) putchar('0'); while(x) { ch[len++]=x%10+'0'; x/=10; } for(int i=len-1;i>=0;i--) putchar(ch[i]); putchar('\n');}int main(){ //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); n=read();m=read(); for(int i=1;i<=n;i++) { a[i].x=read(); a[i].ans=0; a[i].y=i; a[i].id=0; b[a[i].x]=i; } int x,t=0; for(int i=1;i<=m;i++) { x=read(); a[b[x]].id=n+1-i; } for(int i=1;i<=n;i++) if(a[i].id==0) a[i].id=++t; sort(a+1,a+1+n,cmp); work(1,n); sort(a+1,a+1+n,cmp); ll ans=0; for(int i=1;i<=n;i++) ans+=a[i].ans; for(int i=n;i>=n+1-m;i--) { out2(ans); ans-=a[i].ans; } return 0; }
- CQOI2011-动态逆序对
- 【cqoi2011】动态逆序对
- 【CQOI2011】【BZOJ3295】动态逆序对
- 3295: [Cqoi2011]动态逆序对
- BZOJ3295 CQOI2011 动态逆序对
- [BZOJ3295] [Cqoi2011]动态逆序对
- 【bzoj3295】[Cqoi2011]动态逆序对
- bzoj3295: [Cqoi2011]动态逆序对
- bzoj3295【CQOI2011】动态逆序对
- 【Cqoi2011】【BZOJ3295】动态逆序对
- bzoj3295: [Cqoi2011]动态逆序对
- [BZOJ3295][Cqoi2011]动态逆序对
- bzoj3295[Cqoi2011] 动态逆序对
- bzoj3295 [Cqoi2011]动态逆序对
- BZOJ3295: [Cqoi2011]动态逆序对
- bzoj3295: [Cqoi2011]动态逆序对
- 【bzoj3295】[Cqoi2011]动态逆序对
- BZOJ3295: [Cqoi2011]动态逆序对
- Springboot(热部署)
- [分治 杂题] Codeforces Gym 101173 CERC 16 G & BZOJ 4792 Geohash Grid
- 容器配接器(stacks)
- sdut_java_C/C++经典程序训练2---斐波那契数列
- VS+MFC+OPENCV摄像头跟踪蓝色物体并输出坐标并发送
- 【cqoi2011】动态逆序对
- 高斯日记
- RSA根据modulus,exponent生成公钥
- DHTML概述
- 链表求和
- bootstraps 兼容IE 8及以下版本的兼容写法
- sdut_java_C/C++训练1---最大公约数与最小公倍数
- 蓝桥杯 立方尾不变
- 文章标题