bzoj 3295 (洛谷3157、3193) [Cqoi2011]动态逆序对——树状数组套权值线段树

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3295

题目--洛谷3157:https://www.luogu.org/problemnew/show/P3157

题目--洛谷3193:https://www.luogu.org/problemnew/show/P1393

用树套树做的。还能用主席树和CDQ分治做。现在还没用它们做。

有点卡空间。线段树节点的*100怎么算?

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const int N=1e5+5;
int n,m,f[N],rt[N],tot,ps[N];
ll ans;
struct Node{
    int ls,rs,sum;
}a[N*100];
int getsm(int x)
{
    int ret=0;for(;x;x-=(x&-x))ret+=f[x];return ret;
}
void addsm(int x)
{
    for(;x<=n;x+=(x&-x))f[x]++;
}
void insert(int &cr,int l,int r,int p,int fx)
{
    if(!cr)cr=++tot;a[cr].sum+=fx;
    if(l==r)return;
    int mid=((l+r)>>1);
    if(p<=mid)insert(a[cr].ls,l,mid,p,fx);
    else insert(a[cr].rs,mid+1,r,p,fx);
}
void insert(int x,int v,int fx)
{
    for(;x<=n;x+=(x&-x))insert(rt[x],1,n,v,fx);
}
int query(int cr,int l,int r,int x)
{
      if(r<=x)return a[cr].sum;
    int mid=((l+r)>>1);
    if(x<=mid)return query(a[cr].ls,l,mid,x);
    return a[a[cr].ls].sum+query(a[cr].rs,mid+1,r,x);
}
int query(int x,int v)
{
    int ret=0;for(;x;x-=(x&-x))ret+=query(rt[x],1,n,v);return ret;
}
int pre(int p,int x)
{
    return query(p,n)-query(p,x);
}
int suf(int p,int x)
{
    return query(n,x)-query(p,x);
}
int main()
{
    scanf("%d%d",&n,&m);int x;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&x);ans+=getsm(n)-getsm(x);
        addsm(x);insert(i,x,1);ps[x]=i;
    }
    for(int i=1;i<=m;i++)
    {
        printf("%lld\n",ans);scanf("%d",&x);
        ans-=pre(ps[x],x)+suf(ps[x],x);
        insert(ps[x],x,-1);
    }
    return 0;
}

加上离散化就能过洛谷3193了。通过数喜+1。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=4e4+5;
int n,m,f[N],rt[N],tot,vl[N];
ll ans,tp[N],t[N];
struct Node{
    int ls,rs,sum;
}a[N*100];
int getsm(int x)
{
    int ret=0;for(;x;x-=(x&-x))ret+=f[x];return ret;
}
void addsm(int x)
{
    for(;x<=n;x+=(x&-x))f[x]++;
}
void insert(int &cr,int l,int r,int p,int fx)
{
    if(!cr)cr=++tot;a[cr].sum+=fx;
    if(l==r)return;
    int mid=((l+r)>>1);
    if(p<=mid)insert(a[cr].ls,l,mid,p,fx);
    else insert(a[cr].rs,mid+1,r,p,fx);
}
void insert(int x,int v,int fx)
{
    for(;x<=n;x+=(x&-x))insert(rt[x],1,n,v,fx);
}
int query(int cr,int l,int r,int x)
{
    if(r<=x)return a[cr].sum;
    int mid=((l+r)>>1);
    if(x<=mid)return query(a[cr].ls,l,mid,x);
    return a[a[cr].ls].sum+query(a[cr].rs,mid+1,r,x);
}
int query(int x,int v)
{
    int ret=0;for(;x;x-=(x&-x))ret+=query(rt[x],1,n,v);return ret;
}
int pre(int p,int x)
{
    return query(p,n)-query(p,x);
}
int suf(int p,int x)
{
    return query(n,x)-query(p,x);
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%lld",&t[i]),tp[i]=t[i];
    sort(tp+1,tp+n+1);int cnt=unique(tp+1,tp+n+1)-tp-1;
    for(int i=1;i<=n;i++)vl[i]=lower_bound(tp+1,tp+cnt+1,t[i])-tp;
    for(int i=1;i<=n;i++)
    {
        ans+=getsm(n)-getsm(vl[i]);
        addsm(vl[i]);insert(i,vl[i],1);
    }
    printf("%lld ",ans);int x;
    for(int i=1;i<=m;i++)
    {
        scanf("%d",&x);
        ans-=pre(x,vl[x])+suf(x,vl[x]);
        insert(x,vl[x],-1);printf("%lld ",ans);
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/Narh/p/9226453.html