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

洛谷 P3157(同一道题) https://www.luogu.org/problemnew/show/P3157

洛谷 P1393(略有不同) https://www.luogu.org/problemnew/show/P1393

动态逆序对问题;

树状数组套权值线段树,动态开点;

就像树状数组那样做就可以了,每个线段树维护一段区间内的不同权值的数的个数;

删除一个点,就把答案减去它贡献的逆序对数量就可以了;

有点不太懂空间范围怎么算...

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
int const maxn=1e5+,maxm=maxn*;
int n,m,pos[maxn],t[maxn],rt[maxn],ls[maxm],rs[maxm],sum[maxm],cnt;
ll ans;
ll getsum(int x)
{
ll ret=;
for(;x;x-=(x&-x)) ret+=t[x];
return ret;
}
void add(int x)
{
for(;x<=n;x+=(x&-x)) t[x]++;
}
void update(int &x,int l,int r,int p,int v)
{
if(!x)x=++cnt; sum[x]+=v;
if(l==r)return;
int mid=(l+r)>>;
if(p<=mid)update(ls[x],l,mid,p,v);
else update(rs[x],mid+,r,p,v);
}
void insert(int x,int p,int v)
{
for(;x<=n;x+=(x&-x)) update(rt[x],,n,p,v);
}
ll ask(int x,int l,int r,int p)
{
if(l==r)return sum[x];
int mid=(l+r)>>;
if(p<=mid)return ask(ls[x],l,mid,p);
return sum[ls[x]]+ask(rs[x],mid+,r,p);
}
ll query(int x,int p)//<=p 的个数
{
ll ret=;
for(;x;x-=(x&-x)) ret+=ask(rt[x],,n,p);
return ret;
}
ll pre(int x,int p){return query(p,n)-query(p,x);}
ll suf(int x,int p){return query(n,x)-query(p,x);}
int main()
{
scanf("%d%d",&n,&m);
for(int i=,x;i<=n;i++)
{
scanf("%d",&x); pos[x]=i;
ans+=getsum(n)-getsum(x);
add(x); insert(i,x,);
}
for(int i=,x;i<=m;i++)
{
printf("%lld\n",ans); scanf("%d",&x);
ans-=pre(x,pos[x])+suf(x,pos[x]);
insert(pos[x],x,-);
}
return ;
}

洛谷P1393,离散化一下即可。(通过数喜+1)

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int const maxn=4e4+,maxm=maxn*;
int n,m,t[maxn],rt[maxn],ls[maxm],rs[maxm],sum[maxm],cnt,tot;
ll ans,a[maxn],b[maxn];
ll getsum(int x)
{
ll ret=;
for(;x;x-=(x&-x)) ret+=t[x];
return ret;
}
void add(int x)
{
for(;x<=n;x+=(x&-x)) t[x]++;
}
void update(int &x,int l,int r,int p,int v)
{
if(!x)x=++cnt; sum[x]+=v;
if(l==r)return;
int mid=(l+r)>>;
if(p<=mid)update(ls[x],l,mid,p,v);
else update(rs[x],mid+,r,p,v);
}
void insert(int x,int p,int v)
{
for(;x<=n;x+=(x&-x)) update(rt[x],,n,p,v);
}
ll ask(int x,int l,int r,int p)
{
if(l==r)return sum[x];
int mid=(l+r)>>;
if(p<=mid)return ask(ls[x],l,mid,p);
return sum[ls[x]]+ask(rs[x],mid+,r,p);
}
ll query(int x,int p)//<=p 的个数
{
ll ret=;
for(;x;x-=(x&-x)) ret+=ask(rt[x],,n,p);
return ret;
}
ll pre(int x,int p){return query(p,n)-query(p,x);}
ll suf(int x,int p){return query(n,x)-query(p,x);}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)scanf("%lld",&a[i]),b[i]=a[i];
sort(b+,b+n+);
tot=unique(b+,b+n+)-b-;
for(int i=;i<=n;i++) a[i]=lower_bound(b+,b+tot+,a[i])-b;
for(int i=;i<=n;i++)
{
ans+=getsum(n)-getsum(a[i]);
add(a[i]); insert(i,a[i],);
}
for(int i=,k;i<=m;i++)
{
printf("%lld ",ans); scanf("%d",&k);
ans-=pre(a[k],k)+suf(a[k],k);
insert(k,a[k],-);
}
printf("%lld\n",ans);
return ;
}

最新文章

  1. CodeForces 13E 分块
  2. cssSelector定位笔记1
  3. Web Performance Test : 为Request的Post参数名添加XPath支持
  4. linux pxe+dhcp+nfs+tftp
  5. mysql源码解读之事务提交过程(一)
  6. React JS快速入门教程
  7. mybatis的动态sql
  8. 【转】获取手机的ipv4地址
  9. [html][转]常用返回顶部代码
  10. 达夫设备/达夫算法(Duff&#39;s Device)
  11. kafka文档翻译(一)
  12. android 数据共享
  13. 批处理获取IP地址
  14. 浅谈分析表格布局与Div+CSS布局的区别
  15. align-content 与 align-items 区别
  16. SHELL:多文件的重命名和移动
  17. oracle数据库完全卸载步骤
  18. hadoop退出安全模式Name node is in safe mode
  19. tensorflow 1.0 学习:池化层(pooling)和全连接层(dense)
  20. Flask-sqlacodegen

热门文章

  1. CSDN编写技巧--CSDN中高亮显示代码
  2. 3D标签云
  3. Python文件处理(txt、csv文件读取)
  4. 总结:常用的Linux系统监控命令(2)
  5. hihoCoder#1119 小Hi小Ho的惊天大作战:扫雷&#183;二
  6. 天才的记忆(vijos 1514)
  7. Linux下汇编语言学习笔记26 ---
  8. linux 常见名词及命令(三)
  9. Codeforces 628F Bear and Fair Set
  10. DELPHI异步选择模型UDP