3295: [Cqoi2011]动态逆序对
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 861 Solved: 287
[ Submit][ Status]
Description
对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数。给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数。
Input
输入第一行包含两个整数n和m,即初始元素的个数和删除的元素个数。以下n行每行包含一个1到n之间的正整数,即初始排列。以下m行每行一个正整数,依次为每次删除的元素。
Output
输出包含m行,依次为删除每个元素之前,逆序对的个数。
Sample Input
5 4
1
5
3
4
2
5
1
4
2
1
5
3
4
2
5
1
4
2
Sample Output
5
2
2
1
样例解释
(1,5,3,4,2)(1,3,4,2)(3,4,2)(3,2)(3)。
2
2
1
样例解释
(1,5,3,4,2)(1,3,4,2)(3,4,2)(3,2)(3)。
HINT
N<=100000 M<=50000
题意:RT
思路:线段树套平衡树碾压~第一次写,居然1Y了,6420MS,不知道是慢还是快
动态的删除元素,这个可以用线段树来完成,线段树里的每个节点维护一棵平衡树,当要删除一个元素时将包含该元素的所有线段树的节点都插入到节点所对应的平衡树
里面,然后预处理出每个元素的前面有多少个元素比它大和后面有多少个元素比它小,每次查询,只需要在包含的线段里查出比现在要删除的元素大的以及小的,这个可
以在各个节点所维护的平衡树里完成,然后细节看代码吧~~
#include
#include
#include
#include
using namespace std;
#define INF ((1<<31)-1)
#define maxn 100010
#define lson l,m,o<<1
#define rson m+1,r,o<<1|1
typedef long long ll;
struct node{
int v;
int s;
int sz;
node *p;
node *ch[2];
node(){
v=s=sz=0;
p=ch[0]=ch[1]=this;
}
bool cmp(int s)
{
return this->s
ch[1]==o?1:0;
}
}Tnull,*null=&Tnull;
void newnode(node *pre,int d,int v)
{
node *u=(node*)malloc(sizeof(node));
u->ch[0]=u->ch[1]=null;
u->sz=1;
u->s=rand()%INF;
u->v=v;
u->p=pre;
pre->ch[d]=u;
}
void pushup(node *o)
{
o->sz=o->ch[0]->sz+o->ch[1]->sz+1;
}
void rot(node *o,int d)
{
node *k=o->ch[d];
o->ch[d]=k->ch[d^1];
k->ch[d^1]->p=o;
o->p->ch[o->p->cd(o)]=k;
k->p=o->p;
k->ch[d^1]=o;
o->p=k;
pushup(o);
pushup(k);
}
void Insert(node *o,node *pre,int v,int dd)
{
if(o==null){
newnode(pre,dd,v);
return;
}
int d;
if(v>=o->v){
d=1;
Insert(o->ch[1],o,v,1);
}
else {
d=0;
Insert(o->ch[0],o,v,0);
}
if(o->cmp(o->ch[d]->s))rot(o,d);
else pushup(o);
}
int Find(node *o,int v,int vis)
{
if(o==null)return 0;
int ans=0;
if(vis){
if(v
v){ ans+=o->ch[1]->sz+1; ans+=Find(o->ch[0],v,vis); } else ans+=Find(o->ch[1],v,vis); } else { if(v>o->v){ ans+=o->ch[0]->sz+1; ans+=Find(o->ch[1],v,vis); } else ans+=Find(o->ch[0],v,vis); } return ans; } void Free(node *o) { if(o==null)return; Free(o->ch[0]); Free(o->ch[1]); free(o); } node *tree[maxn<<2]; void STbuild(int l,int r,int o) { tree[o]=(node*)malloc(sizeof(node)); tree[o]->ch[0]=tree[o]->ch[1]=null; if(l==r)return; int m=l+r>>1; STbuild(lson); STbuild(rson); } void STinsert(int l,int r,int o,int v,int p) { Insert(tree[o]->ch[1],tree[o],v,1); if(l==r)return; int m=l+r>>1; if(p<=m)STinsert(lson,v,p); else STinsert(rson,v,p); } int STquery(int l,int r,int o,int L,int R,int v,int vis) { if(L<=l&&r<=R)return Find(tree[o]->ch[1],v,vis); int m=l+r>>1; int ans=0; if(L<=m)ans+=STquery(lson,L,R,v,vis); if(m
>1; FreeST(lson); FreeST(rson); } int niq[maxn]; int nih[maxn]; int sum[maxn]; int getbit(int x) { return (-x)&x; } void addbit(int n,int maxi) { while(n<=maxi) { sum[n]++; n+=getbit(n); } } int sumbit(int n) { int ans=0; while(n) { ans+=sum[n]; n-=getbit(n); } return ans; } int a[maxn]; int pos[maxn]; int ha[maxn]; int main() { int n,m; while(scanf("%d%d",&n,&m)!=EOF) { int i,v; memset(sum,0,sizeof(sum)); memset(ha,0,sizeof(ha)); for(i=1;i<=n;++i) { scanf("%d",&a[i]); pos[a[i]]=i; niq[i]=sumbit(n)-sumbit(a[i]); addbit(a[i],n); } memset(sum,0,sizeof(sum)); ll ans=0; for(i=n;i>=1;--i) { nih[i]=sumbit(a[i]-1); addbit(a[i],n); ans+=nih[i]; } STbuild(1,n,1); for(i=0;i
=1&&v<=n){ ha[v]=1; ans-=niq[pos[v]]; ans-=nih[pos[v]]; if(pos[v]>1)ans+=STquery(1,n,1,1,pos[v]-1,v,1); if(pos[v]