[CQOI2011]动态逆序对

emmm

显然的考虑影响

后面比x小的

前面比x大的

还要单点修改

只有树套树了。

 

暴力无脑线段树套fhq 会TLE到80pts

单点修改,区间查询

树状数组套动态开点线段树显然更优啊

2781ms

// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define il inline
#define reg register int
#define numb (ch^'0')
#define mid ((l+r)>>1)
using namespace std;
typedef long long ll;
il void rd(int &x){
    char ch;bool fl=false;
    while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
    for(x=numb;isdigit(ch=getchar());x=x*10+numb);
    (fl==true)&&(x=-x);
}
namespace Miracle{
const int N=100000+5;
int n,m;
int a[N];
int p[N];
int b[N];
struct arraytree{
    int f[N];
    void add(int x){
        for(;x<=n;x+=x&(-x)) ++f[x];
    }
    int query(int x){
        int ret=0;
        for(;x;x-=x&(-x)) ret+=f[x];
        return ret;    
    }
}at;
struct node{
    int ls,rs;
    int sz;
}t[N*200];
int tot;
int rt[N];
void upda(int &x,int l,int r,int p,int c){
//    cout<<" upda "<<l<<" "<<r<<" to "<<p<<" and "<<c<<endl;
    if(!x) x=++tot;
    t[x].sz+=c;
    if(l==r) return;
    if(p<=mid) upda(t[x].ls,l,mid,p,c);
    else upda(t[x].rs,mid+1,r,p,c);
}
int query(int x,int l,int r,int L,int R){
    //cout<<" query "<<l<<" "<<r<<" find "<<L<<" "<<R<<endl;
    if(L<=l&&r<=R){
        return t[x].sz;
    }
    int ret=0;
    if(L<=mid) ret+=query(t[x].ls,l,mid,L,R);
    if(mid<R) ret+=query(t[x].rs,mid+1,r,L,R);
    return ret;
}
void build(){
    for(int i=1;i<=n;++i){
    //    cout<<" ii "<<i<<endl;
        for(reg j=(i-(i&(-i)))+1;j<=i;++j){
        //    cout<<"jjjjjjjjjj "<<j<<endl;
            upda(rt[i],1,n,a[j],1);
        }
    }
}
int wrk(int x,int l,int r){
    if(l>r) return 0;
    int ret=0;
    for(;x;x-=x&(-x)){
        ret+=query(rt[x],1,n,l,r);
    }
    return ret;
}
void dele(int x){
    int pos=p[x];
    for(;pos<=n;pos+=pos&(-pos)){
        upda(rt[pos],1,n,x,-1);
    }
}
int main(){
    rd(n);rd(m);
    ll ans=0;
    for(reg i=1;i<=n;++i) {
        rd(a[i]);
        b[i]=a[i];
        p[a[i]]=i;
    }
    for(reg i=n;i>=1;--i){
        ans+=at.query(a[i]-1);
        at.add(a[i]);
    }
    
    int x;
    
    printf("%lld\n",ans);
    build();
//    cout<<" after build-----------------------------------"<<endl;
    while(m--){
        rd(x);
    //    cout<<" xx "<<x<<" p[x] "<<p[x]<<endl;
        if(p[x]!=n) {
            ans-=wrk(n,1,x-1)-wrk(p[x],1,x-1);
        }
        if(p[x]!=1){
            ans-=wrk(p[x]-1,x+1,n);
        }
        dele(x);
        if(m) printf("%lld\n",ans);
    }
    return 0;
}

}
signed main(){
    Miracle::main();
    return 0;
}

/*
   Author: *Miracle*
   Date: 2019/1/20 17:23:51
*/

 

转载于:https://www.cnblogs.com/Miracevin/p/10295998.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值