题意
分析:
没过是因为没看。。。
这题其实相当水。。。
重新定义一下逆序对:每个点的贡献为,其后面的,比它小的数的个数。
然后这样一来,每次排过序之后的点,其后面就不可能有比它小的值了,直接忽略以后排序又排到它的情况。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define SF scanf
#define PF printf
#define MAXN 200010
#define INF 0x3FFFFFFF
using namespace std;
typedef long long ll;
int n,m;
int a[MAXN];
ll f[MAXN],ans;
ll tr[MAXN*4];
void build(int l=1,int r=n,int id=1){
int mid=(l+r)>>1;
if(l==r){
tr[id]=a[l];
return ;
}
build(l,mid,id<<1);
build(mid+1,r,id<<1|1);
tr[id]=min(tr[id<<1],tr[id<<1|1]);
}
ll tree[MAXN];
ll find(int x){
int res=0;
while(x){
res+=tree[x];
x-=x&(-x);
}
return res;
}
void add(int x){
while(x<=n){
tree[x]++;
x+=x&(-x);
}
}
int find(int l1,int r1,int val,int l=1,int r=n,int id=1){
if(tr[id]>val)
return -1;
if(l==r){
tr[id]=INF;
return l;
}
int res=-1;
int mid=(l+r)>>1;
if(l1<=mid){
res=find(l1,r1,val,l,mid,id<<1);
tr[id]=min(tr[id<<1],tr[id<<1|1]);
if(res!=-1)
return res;
}
if(r1>mid){
res=find(l1,r1,val,mid+1,r,id<<1|1);
tr[id]=min(tr[id<<1],tr[id<<1|1]);
if(res!=-1)
return res;
}
return res;
}
int main(){
freopen("count.in","r",stdin);
freopen("count.out","w",stdout);
SF("%d%d",&n,&m);
for(int i=1;i<=n;i++)
SF("%d",&a[i]);
for(int i=n;i>=1;i--){
if(a[i]!=1)
f[i]=find(a[i]-1);
ans+=f[i];
add(a[i]);
}
build();
PF("%lld ",ans);
int t;
for(int i=1;i<=m;i++){
SF("%d",&t);
int id=find(t,n,a[t]);
while(id!=-1){
ans-=f[id];
id=find(t,n,a[t]);
}
PF("%lld ",ans);
}
}